Grow your CSS skills. Land your dream job.

Prevent White Flash While iFrame Loads

Published by Chris Coyier

If you Google around about this problem (at the time of this writing), you'll find some incomplete answers and some other snippets advocating this bad practice:

<!-- NO! Bad! -->
<iframe src="..." style="visibility:hidden;" onload="this.style.visibility='visible';"></iframe>

The reason this is bad is that the CSS will hide the iframe no matter what and users with JavaScript turned off will never see that iframe. Now I'm not usually one to go to extreme lengths to cater to that crowd, but I'm all for using better solutions that do solve that issue when they are available.

The Solution

Thanks to Paul Irish and his Surefire DOM Element Insertion and Ryan Seddon and his article on inserting scoped style elements, we have this:

// Prevent variables from being global      
(function () {

      /*
          1. Inject CSS which makes iframe invisible
      */
    
    var div = document.createElement('div'),
        ref = document.getElementsByTagName('base')[0] || 
              document.getElementsByTagName('script')[0];

    div.innerHTML = '&shy;<style> iframe { visibility: hidden; } </style>';

    ref.parentNode.insertBefore(div, ref);

        
    /*
        2. When window loads, remove that CSS, 
           making iframe visible again
    */
    
    window.onload = function() {
        div.parentNode.removeChild(div);
    }
    
})();

Just include that on any page (in the <head>) with the white flash problem and it will be solved. Just note that we're using window.onload here, so if your page also uses that somewhere, combine them.

How it Works

  1. It inserts some CSS on the page (right away) which makes all iframes invisible. You can't see a white flash on an iframe that's not there!
  2. When the window is done loading (which means iframes are done loading too), this CSS is removed, which makes the iframes visible again

Browsers Affected

At the time of this writing, I'm able to replicate the problem in Chrome 11 and Safari 5 (so essentially a WebKit issue). Current Firefox, Opera, and IE are fine.

What About... other stuff?

You can put the allowtransparency="true" attribute on the iframe. You can set the iframe's background to transparent with CSS. You can make sure the background on the source document matches the background of the parent page. None of that stuff works. This works. Well... it works for users with JavaScript turned on, anyway. =)

Comments

  1. What’s the “&shy;” all about?

  2. (that was a “shy” character… whatever that means)

  3. Lee

    Why not just have a <noscript> tag with a normal iframe, and add the iframe via javascript for everyone else?

    • Lee

      It cleared my html, it should read:

      Why not just have “noscript” a tag with a normal iframe, and add the iframe via javascript for everyone else?

    • I’m not sure that would help. When the JS inserts the iframe, it still loads and still white flash. Except you could probably do the same trick of hiding visibility until it loads. Seems kinda un-scaleable to have to put the markup for every iframe you want to insert into the JavaScript, kinda crossin’ the ol’ streams of content and behavior.

    • You would still have to use javascript so I think this solution is easier and it should work without editing the page, just “paste it and go”

  4. Hejsa!

    Wonderful article!

    One thing though: I’m sure you mean “You can’t see a white flash on an iframe that’s not there!”

  5. Nice Article, but in general, the iFrame-technique is sooo old. You’ll better make clear to use other methods like dynamic content via PHP.

    • iFrames are here to stay for a while man. I think it’s a perfectly fine thing. YouTube videos are iframe embeds. Wufoo forms are iframe embeds. They are really great for hosted third party content where you need/want the control of those two things to be separate.

    • The iFrame Support from popular Webservices like YouTube, Facebook etc. does not mean that iFrames are a good way to handle external content. There are modern solutions like SOAP or CURL to handle this. (Sorry for my bad english, i’m from germany)

    • tommy

      i have to agree with Chris. i work for a large corporation and we have a new, large SaaS product that is 100% reliant on iFrames.

    • So you think YouTube videos should provide their copy-and-paste embeddable video code as PHP with a CURL call?

    • iFrames are a perfect way to house outside content and as Chris said, with more and more large companies using them to embed there content (Youtube, Vimeo, Facebook, Twitter…) they are here to stay for a long time.

    • >> So you think YouTube videos should provide their copy-and-paste embeddable video code as PHP with a CURL call?

      Yes, why not. Its also possible to share a JSON/XML/Whatever-Interface, which is easy callable via JavaScript.

    • I think that an iFrame makes it easy for people that are not in the design field or used to looking at a piece of code. For a large percentage of people its hard enough just to copy and paste. That could have been a reason for YouTube to switch to iFrame embed as it looks less complicated..

      I implemented this flash prevention code on my site as soon as I saw it.

      Thanks and great work Chris.

  6. cnwtx

    Does this also work if the iframe has been inserted with javascript?
    I.E. :

    function showNavIFrame()
    	{
    	var iframe = document.createElement("iframe");
    	iframe.setAttribute("id","navbar-iframe");
    	iframe.setAttribute("frameBorder","0");
    	iframe.setAttribute("scrolling","no");
    	iframe.setAttribute("allowtransparency","true");
    	iframe.setAttribute("src","./navbar.htm");
    	window.document.body.appendChild(iframe);
    	return false;
    	}
  7. thnx it was very useful.i will use this in my site

  8. This is actually a great way of preventing unwanted flashes of styling on things like skinned dropdowns and custom scrollbars. Happy to see this method catching on and being used for iframes as well!

  9. Hassan

    “Just note that we’re using window.onload here, so if your page also uses that somewhere, combine them.”
    Why? I thought when you register multiple functions for an event, they stack and run in turn. Isn’t that so?
    BTW, did you know you can get the content of the iframe via script? All you need is this:
    getElementById('myiFrame').contentWindow and it will return the ‘window’ object of that iframe, now you can go like this:

    getElementById('myiFrame').contentWindow.document.getElementById('whatever_inside_iframe')
    • Here’s a fiddle with two declarations of window.onload: http://jsfiddle.net/chriscoyier/gb7gt/ — you only get the second one. There may be a better way to handle that. I’m a noob at JavaScript.

      For that second bit about accessing internal contents of iframe, that only works for same-domain iframes I’m pretty sure.

    • DED

      Chris is correct, ‘window.onload’ can only be attached to one function call. Using it twice means only the second call is fired. To do what you are suggesting Hassan, you would use an ‘init’ type function to run at ‘window.onload’ and then make multiple function calls to get the stacking behavior you’re describing.

    • Yeah totally, that’s why I said to watch out for that in the article and combine them. That’s the ideal way to do it, like you said, create an init function and call that, which contains anything you want to run on window.onload

    • the “proper” way is to use “attachEvent” for IE and “addEventListener” for everything else. That allows you to attach as many callbacks to an event as you want.

  10. Chris

    I managed to get rid of that white iframe flash with a site by simply using a background color with css for iframe element. Not suitable for image backgrounds but an option none the less on occassion

  11. Thank you for such good and juicy article post :)
    This is definitely can be helpful when I’m dealing with Flash.

  12. ref = document.getElementsByTagName(‘base’)[0] ||
    document.getElementsByTagName(‘script’)[0];
    WOW!!!

  13. Kuif

    What about when using this for a page with an iframe where every click on a menu-item loads different content in the same iframe. The page wont reload, only the iframe content. How to edit your script to prefent that kind of white flash?

  14. Thanks, I’ve been looking for a solution to that problem for an hour! It doesn’t look good when its a payment gateway in the iframe, customers can loose confidence quite easily.

  15. I am having an issue with this working in fancybox (www.fancybox.net). The fancybox uses an iframe so this works to a degree. The only problem is that once the page is loaded within the fancybox the css is not removed and the content remains hidden.

    Is anyone familiar with fancybox enough to help me out? I’m new to javascript as well and I am sure it is a simple tweak that will fix this, but I am not sure where to start.

  16. Adrian

    How can I add this code to my page? Do I need to insert within tags? Or tags??

    I’m trying to have this work on an iframe embedde in a scene within a Hype (http://www.tumultco.com/hype/) site. The page with the iFrame is accesed as a scene and therefore the page doesn’t exactly ‘load’.
    The iframe link is added within an inner HTML window.

    Can I add this code elsewhere?

    If not what other answer above best suits, perhaps adding custom CSS inside or alongside the iframe code?

    Thanks!

  17. Max
    Permalink to comment#

    Hi Chris. Thanks for helping. I pasted the code into the head as you say. The flash is gone but the video as well. Only hear audio. Why?
    Regards,

This comment thread is closed. If you have important information to share, you can always contact me.

*May or may not contain any actual "CSS" or "Tricks".