Aaron Peters

Iframe Loading Techniques and Performance

This article is 9+ years old. Do not assume any recommendations are still valid today. And my old test pages are broken (404).
Iframe setTimeout() does not work in IE9.
Chad Barnsdale of Unfinishedman.com mentioned to me on May 25 that the Iframe setTimeout() technique does not work in IE9. And he was right. The file that gets loaded into the iframe simply does not load. Nothing happens. I will dive into this sometime soon. It's probably something small with the JavaScript code.

Iframes are often used to load third party content, ads and widgets. The main reason to use the iframe technique is that the iframe content can load in parallel with the main page: it doesn't block the main page. Loading content in an iframe does however have two downsides, as Steve Souders outlines in his blog post Using Iframes Sparignly

  • Iframes block onload of the main page
  • The main page and iframe share the same connection pool

The onload blocking is the biggest problem of the two and hurts performance the most. You really want the load event to fire as soon as possible, for optimal user experience of course but also because of how Google measures your site speed: Google Toolbar in IE and FF browsers of site visitors measures time to onload.

How can you load an iframe without blocking onload and as a result improve page performance?

This article shows 4 ways to load an iframe in a web page: Normal Iframe, Iframe After Onload, Iframe setTimeout() Dynamic Asynch Iframe. For each the behaviour related to the load event is described and shown by way of IE8 waterfall charts. I recommend to look closely at the Dynamic Asynch Iframe technique because this one is great for performance. Oh, and as a bonus, I throw in the Friendly Iframe technique. It doesn't really qualify as an iframe loading technique, but it has to do with iframes, ads and (non)-blocking.

Normal Iframe

You all know this one. It's the default way to load an iframe and works in all browsers:

<iframe src="/path/to/file" frameborder="0" width="728" height="90" scrolling="auto">
</iframe>

Using the Normal Iframe technique will result in the following behaviour in all browsers:

  • Iframe starts loading before onload of main page
  • Onload of the iframe fires after all iframe content is done loading
  • Onload of main page fires after the iframe's onload fires: the iframe blocks the main page onload !
  • While the iframe is loading, one or more browser busy indicators show something is loading

I created a simple test page and ran it through Webpagetest.org (IE7 and IE8). The waterfall chart below clearly shows how the Normal Iframe blocks the main page onload.

Normal Iframe - Performance - IE8 waterfall chart

Click image for a bigger version

My advice: be aware of the onload blocking. It's not a big problem if the iframe content takes a short time to load (and execute), and the iframe in itself is good to use because it loads in parallel with the main page. But if it takes long for the iframe to finish, the user experience is damaged. Test it on your page(s) and run it through Webpagetest.org a few times, look at the impact on onload (Doc Complete time) and decide if you need a better technique.

Iframe After Onload

Imagine you want to load something in an iframe, but it's not really important for the page. Or the content of the iframe is not immediately visible to the user because it's way down below the fold or hidden behind a link/tab. Consider deferring the loading of the iframe until after the main page is done.

<script>
//doesn't block the load event
function createIframe(){
var i = document.createElement("iframe");
i.src = "path/to/file";
i.scrolling = "auto";
i.frameborder = "0";
i.width = "200px";
i.height = "100px";
document.getElementById("div-that-holds-the-iframe").appendChild(i);
};

// Check for browser support of event handling capability
if (window.addEventListener)
window.addEventListener("load", createIframe, false);
else if (window.attachEvent)
window.attachEvent("onload", createIframe);
else window.onload = createIframe;
</script>

The Iframe After Onload technique will consistently show the following behaviour in all browsers:

  • Iframe starts loading after onload of main page
  • Onload of main page fires without interference of the iframe: the iframe does not block the main page onload !
  • While the iframe is loading, one or more browser busy indicators show something is loading

I ran some tests with my Iframe After Onload test page on Webpagetest.org (IE7 and IE8): as expected, onload is not blocked:

Iframe After Onload - Performance - IE8 waterfall chart

Click image for a bigger version

What do you gain by this versus the Normal Iframe? The load event of the main page fires sooner, and this has 2 benefits:

  • Other code waiting for the load event can load/execute sooner
  • Google Toolbar measures a much lower Time to Onload, which helps improve Google's perception of your site speed

Unfortunately, your site visitors will still see browser busy indicator(s) while the iframe is loading and that means that they will see those indicators for a longer period of time (versus Normal Iframe). Another downside of loading the iframe after onload is that there is a bigger chance the user leaves the page before the iframe has finished loading. In some cases this may be a real problem, e.g. you have a deal with a ad/widget provider that is based on # impressions.

Iframe setTimeout()

The objective is to load the iframe without blocking onload. Steve Souders (him again) published a demo page for this 'trick' some time ago. He writes:

"the SRC is set dynamically in a function called via setTimeout. This technique avoids the blocking behavior of iframes in all browsers".

And that is not 100% true. I did several tests with his demo page in many browsers and found out that in IE8 - but not in IE7 (!?) - the main page onload is blocked on first visit (empty cache), but not on subsequent visits (primed cache). I saw the same results on my own little test page. Conclusion: this technique will often not have the desired effect in IE8, a popular browser. Too bad!

<iframe id="iframe1" src="" width="200" height="100" border="2"></iframe>
<script>
function setIframeSrc() {
var s = "path/to/file";
var iframe1 = document.getElementById('iframe1');
if ( -1 == navigator.userAgent.indexOf("MSIE") ) {
iframe1.src = s;
}
else {
iframe1.location = s;
}
}
setTimeout(setIframeSrc, 5);
</script>

In all browsers but IE8, the Iframe setTimeout() technique will consistently show the following behaviour:

Iframe starts loading before onload of main page

  • Onload of the iframe fires after all iframe content done loading
  • Onload of main page fires soon: the iframe does not delay the main page onload (note: except in IE8 with empty cache)
  • Why does the iframe not block main page onload in all-but-IE8 browsers? Because of the setTimeout()
  • While the iframe is loading, one or more browser busy indicators show something is loading

I ran tests on Webpagetest.org (IE7 and IE8) with Iframe After Onload test page A and Iframe After Onload test page B: all is fine in IE7, onload is blocked on first view in IE8.

Iframe setTimeout - Performance - IE8 waterfall chart

IE8 first view. Click image for a bigger version

Iframe setTimeout - Performance - IE8 Repeat View waterfall chart

IE8 repeat view (note: my HTML is cached for 10 minutes, so only iframe content is reloaded). Click image for a bigger version

Because of the IE8 issue I believe this technique is not usable in production for many sites. If more than 10% of your visitors have IE8, 1 in 10 will get a lesser experience. You could argue that it's only worse compared to the Normal Iframe technique which isn't a really bad for performance anyway. And onload firing later for 10% of your users ... ah well. You decide, but not after you read below about the ultra awesome Dynamic Asynch Iframe-technique.

Dynamic Asynch Iframe

When I was at the Velocity 2010 web performance conference, two Meebo engineers @marcuswestin and Martin Hunt) gave a presentation about the new Meebo Bar and how they improved this widget's performance. They came up with a truly non-blocking, instantly loading technique for including their widget in a page, using an iframe. For many web developers, their 'dynamic asynch iframe' approach was new. And it's awesome. Double awesome. For some reason, this technique has not gotten the attention it deserves. I hope this blog post can help spread the word.

<script>
(function(d){
var iframe = d.body.appendChild(d.createElement('iframe')),
doc = iframe.contentWindow.document;

// style the iframe with some CSS
iframe.style.cssText = "position:absolute;width:200px;height:100px;left:0px;";

doc.open().write('&lt;body onload="' +
'var d = document;d.getElementsByTagName(\'head\')[0].' +
'appendChild(d.createElement(\'script\')).src' +
'=\'\/path\/to\/file\'"&gt;');

doc.close(); //iframe onload event happens
})(document);
</script>

The magic is in the <body onload="">: the iframe has no content initially, so onload of the iframe fires instantly. Then, you create a new script element, set its source to the JS file that loads the content/ad/widget, append the script to the HEAD and voila: the iframe content loads without blocking the main page onload!

You should see the following behaviour of the Dynamic Asynch Iframe technique consistently in all browsers:

  • Iframe starts loading before onload of main page
  • Onload of the iframe fires instantly, because the iframe content is loaded after onload (yeah!)
  • Onload of main page fires without interference of the iframe: the iframe does not block the main page onload !
  • Why does the iframe not block main page onload? Well, that is because of the <body onload="">
  • If you would not use the onload handler in the iframe, the iframe loading would delay the main page onload
  • While the iframe is loading, no browser busy indicators are active (yeah!)

My Dynamic Asynch Iframe test page gave this result on Webpagetest.org (IE8):

Iframe Dynamic Asynch - Performance - IE8 waterfall chart

Click image for a bigger version

Espacing characters makes it more difficult to read and error prone, but in my opinion these are minor cons. Do give this technique a try and post a comment if it works, or doesn't.

Friendly Iframe

This technique is for ads. It's not really an iframe loading technique, but more of a way to use an iframe to hold ads. The magic is not in how the iframe is loaded, but in how the main page, the iframe and ad codes work together. It works like this:

  • Create an iframe. Set the source to a small static html page from the same domain
  • Inside the iframe, set the JavaScript variable inDapIF = true to tell the ad it is loaded inside a friendly iframe
  • Inside the iframe, create an script element with the ad url as the source. Load the ad just like a normal JavaScript ad
  • When the ad has finished loading, resize the iframe to fit the dimensions of the ad.

The Friendly Iframe works in all browsers.

The Ad Ops Council of the IAB has been recommending this technique since October 2008 as per their Best Practices for Rich Media Ads in Asynchronous Ad Environments (PDF). AOL uses this technique and Dave Artz of AOL describes it in his Velocity 2009 presentation: download PDF. Wanna see code? Dave has a Friendly Iframe test page on his blog. Aftonbladet - a large publisher in Sweden - had good results with the Friendly Iframe: on their Homepage, load time went down by 30%, visits/week went up by 7% and click-throughs to the Latest News section increased by 35%! I recommend watching the Aftonbladet presentation High Performance Web Sites, With Ads: Don't let third parties make you slow

I've not created a test page for the Friendly Iframe, so I don't have any hands-on experience with it. From what I've read so far, and by reviewing and using Dave Artz' test page, this is my view on the Friendly Iframe:

  • It is not useful if you simply want to load a single iframe on a page with a fixed src
  • It's a good technique for loading one or more ads on a web page, in a flexible way: load any ad, update the iframe with another ad, ...
  • The DOMContentLoaded event of the main page is not blocked and neither is page rendering: yeah!
  • However, the load event of the main page is blocked

Iframe Performance Links

Webmentions