Earlier this year I gave a talk at FullStack conference in London about making iFrames cool again (sorry, you have to log in to see the video — if anyone is listening over at FullStack, it would be really awesome if you could make these videos public!)
Why even bother with iframes?
In a nutshell: iframes let you build user experiences into embeddable ‘cross-domain components’, which let users interact with other sites without being redirected. There are a metric ton of awesome uses for that other than tracking and advertizing. Nothing else comes close for this purpose; and as a result, I feel we’re not using iframes to their full potential.
There are big problems, though
The talk covered some of the things that iframes (and also popup windows) are really bad at:
- They have a terrible reputation; historically they’ve been used pretty much exclusively for advertizing and tracking.
- They’re slow to load, resulting in a pretty terrible user experience.
- Communication is tricky: messages are fire-and-forget, with no real error handling or responses, or passing any interesting data types
- Cross-browser issues and implementation differences are common, and less frequently discovered and fixed than other categories of cross-browser bug.
- Security is problematic, and many other classes of vulnerability need to be taken into account when dealing with cross-browser iframes
- Popups can only be opened at limited times (usually on a button click), as a prevention mechanism for popup ads
- Cookie support is limited; with third-party-cookies-disabled mode, and intelligent tracking prevention (ITP) becoming more and more common.
- Real-estate is limited; by default iframes are constrained to their original size and will not resize to fit any child content. And because they’re sandboxed on the page, it’s not possible to render from within an iframe to another part of the page.
- Generally speaking: they don’t act like the components we’ve come to know and love, from libraries like React
Are there solutions?
My talk went into how at PayPal, we built zoid to solve some of the major problems with iframes and popups:
Zoid adds the following nice features to iframes and popups:
- Pre-render to avoid the perception of slow rendering
- Automatically resize frames to fit child content
- Render from inside an iframe to other parts of the page
- Pass down any kind of data and functions/callbacks as props (just like React), and avoid the nightmare of cross-domain messaging between windows.
- Make iframes and popups feel like first class (cross-domain) components.
So we’re good?
Yes, and no.
Because fundamentally: the idea of cross-domain embeddable components is actually pretty useful once you start talking about shareable user experiences, rather than just user-tracking and advertizing which are obviously pills nobody enjoys swallowing.
So here’s my list:
Prevent click-jacking once and for all
There should be a way, from inside an iframe, to check:
Is this iframe fully visible, and at the top level, on the parent page? This would involve checking:
- Is the frame at 100% opacity
- Are there any elements hovering over the frame
- Did a click pass through any hovering elements using pointer-events: none?
This would allow iframes to truly trust clicks, and perform actions that would be risky otherwise. (that is, any action that you need to be logged in to do otherwise, like send a message, or approve a transaction, or change a setting on your profile, or anything else).
Provide a way to easily view the domain of an iframe
This could be implemented as a secondary url bar when hovering the cursor over an iframe or focusing on an element inside of it, or something to give the user an idea of the domain they are interacting with at any given time.
Without this: it is literally impossible without going into the browser dev tools, for a user to verify which domain they are dealing with or entering information on. Which makes building components that accept user input extremely nebulous.
Provide a permission mechanism for cookies
Yes, preventing tracking and advertizing is a reasonable goal. No argument from me.
But third-party-cookie restrictions and intelligent tracking prevention also have a negative impact on iframes that expose embedded experiences, and have little or nothing to do with tracking. If I build an embeddable iframe based component, it would be nice to at least have a way to request permission from the user to read and write cookies from inside that iframe.
This permission could even be granted only after an actual user interaction with the iframe, to prevent hidden frames introducing a lot of permissioning request noise to users.
The Storage Access API goes some way to solving this problem, but as of yet it’s largely unimplemented in most major browsers.
Add a way to pass window references through iframes
This is a little bit more of a technical request; but right now there’s absolutely no way to send a reference to a different window (popup or iframe) through a postMessage.
That makes life extremely difficult sometimes to find references to windows when you need to message them, without recursively traversing
window.frames or using some other mechanism (I outlined them all here). Sometimes, there is no available mechanism to get a reference, which results in hacky approaches like post-robot’s ProxyWindow.
Allowing sending a reference to a window using postMessage, or providing some kind of
getWindowByID would be entirely safe (the actual contents of the window would remain totally sandboxed). It would be great if browsers could support that to avoid some of the existing hacky approaches.
(if anyone is interested in some real world use-cases, please let me know, I have a bunch)
Allow iframes to be rendered with high priority
Right now iframes are often delayed by browsers behind every other thing. I would love to have some way to set a higher priority, which indicates: the UI loaded in this iframe is really important to the user experience, so please start loading it as soon as possible.
I’m sure this has not been added already because the assumption is that most iframes are used for tracking, and if tracking is lazy, that’s less of a problem. But user experiences should be as snappy as possible.
Right now zoid does a pretty good job at ironing over the cracks in iframes, and solving any problem that it’s possible to solve without browser implementation or api changes.
For everything else, I really hope browser vendors start to treat UI based iframes as more of a first-class citizen on the web, and help fix some of the above issues which are not poly-fillable right now.
I really like the work that has been done on portals so far. I just hope iframes don’t get left behind.