Prevent White Flash While iFrame Loads

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. =)