Working with iFrames is often considered a dark, mysterious corner of web design. They are often used as a last ditch effort to integrate content that you otherwise don’t have a good way to pull into your website or application. However, the reality is that iFrames are just a tool like any other & they can have a role to play even in modern web applications. A lot of advice you’ll find online for working with iFrames is shrouded in mystery & misunderstanding about how they work and what you can do with them. This promotes the general sense of dread that developers have about using iFrames, that they are often uncontrollable & prone to unexpected failure.
Overall I would say most of the issues folks encounter with iFrames are actually not problems with iFrames at all, but rather the security policies that govern them & any other external resource loaded by a webpage. The underlying issue is that browsers treat content differently based on whether it complies with the same-origin policy. This means that the parent content, and requested resource must share the same origin.
You can learn more about the same-origin policy and how it applies to content loaded to your webpage by checking out Mozilla’s great article on this topic.
There are many other issues common to working with iFrames, but one especially interesting problem is the curious case of iOS’s Safari iFrame height calculation. This problem is unique to iOS’s Safari browser, and is based in an opinionated choice on Apple’s part to streamline scrolling interactions in their browser across iFrame scroll regions. Like many vendor specific browser fixes, its behavior is a source of much developer confusion and frustration.
The issue is that generally browsers respect the defined height of the iFrame element, and if there is scrolling enabled on the element and the content within it, it will allow scrolling within the iframe. Except for iOS’s Safari browser…
Here we can see that what the iOS Safari browser does instead is resize the iFrame element to the height of its content. This effectively moves the scroll to the parent page instead. Which can generally be identical visually to the user, unless your iFrame actually relies on setting its own scroll position. This single addition can be a huge ‘gotcha’ for developers to overcome when working with iFrames.
However, there are a number of solutions to this problem, one option is to provide a scroll position below the body of the iFrame in a separate scroll container. This appears to by-pass the custom vendor behavior of iOS Safari and instead acts as you would usually expect. Any scroll behavior within the iFrame would instead need to target this scroll container within itself instead of the usual html or body of the document.
Another approach is to simply detect that the iFrame’s content has a parent, and proxy the scroll behavior up to that parent page. This approach relies on a little more coordination between the child iFrame and host parent page, but solves the problem directly through proxying the intent of the child to the parent. Either of these approaches solve this issue, but require some configuration to accomodate this vendor specific iOS Safari iFrame behavior.
It took quite a while to trial and error these solutions. To assist others investigating this issue, I have made a demo of how to apply the scroll proxy solution to an iFrame.
In conclusion, what iFrames excel at is integrating content from an outside source into another application while sandboxing its content from that host application. While this is possible to do through component CSS approaches & well modularized applications, it’s not nearly as easy to drop-in or control as with an iframe based approach. Debugging strange iFrame issues is part of the territory when working with iFrames, but understanding the issues behind these problems can lead to reasonable solutions that make working with them in your application more approachable.