1 Way To Avoid the Flash of Unstyled Content

This tutorial describes a way to avoid a flash of unstyled content that sometimes occurs when applying styles with JavaScript on page load. The problem is most evident when there is some content that needs to be hidden initially and when the document is large or complex. We can see an example of the problem on this test page.

The page is a copy of a previous entry on this blog with over 140 comments—quite a lot of content. Look for the bright yellow background before the page finishes loading. That's the part that is supposed to be hidden from the start — a simple unordered list, <ul id="flash">.

In pages with a more reasonable length, the standard jQuery code would work just fine:

[js]$(document).ready(function() { $('#flash').hide(); });[/js]

But in this page there is a whole lot of document that has to be ready before anything inside the $(document).ready() function can be executed. Too much, in fact. And putting the <script> tags just inside the closing </body> tag doesn't help either. No, using JavaScript to hide elements like this just won't work unless the scripts are placed in the HTML immediately following the elements they're hiding.

Why Use JavaScript for This, Anyway?

Before we examine how to fix the problem, we might need to answer the question, Why bother? I mean, isn't that what CSS is for? Certainly we could add a rule to our stylesheet, such as #flash {display: none;}, and our problem would be solved.

But the pure CSS solution introduces another problem: the hidden content is completely unavailable to those who have CSS enabled/available but JavaScript disabled/unavailable. These users simply won't be able to view the content. Now, some developers don't have a problem with that, but as a proponent of Progressive Enhancement™, I believe that a user should be able to see content at the very least when visiting a web page (okay, okay, full-scale RIAs could be an exception).

A Simple Solution

Rather than attempt a pure CSS solution or a pure JavaScript solution, why not try a hybrid of the two? Here is how it might look (Important: I'm embedding styles and scripts here for the purpose of demonstration, but linking to separate files instead is recommended):

[html] [/html]

The first thing to note here is that the CSS is hiding an element with id="flash" only if it is a descendent of an element with class="js". Now, which element can we add a class of "js" to immediately, from within the <head>, and have it be applied before the slightest bit of the body is visible? Why, the <html> element, of course!

Line 9 shows the "js" class being added. And since it's being added with JavaScript, only those users who have JavaScript enabled will have their <ul id="flash"> initially hidden. Take a look at the beautiful invisibility demonstrated here.

Significantly, the .addClass() method is not inside $(document).ready(). If we had put it inside, we'd be back to square one.

If you follow the YUI advice to put scripts at the bottom, we can still make this solution work for you. We just use ye plain olde JavaScript for our one-liner to add the "js" class, keep that one in the <head>, and dump the other scripts down below, like so:

[html] [/html]

Thanks to Brandon Aaron for the tip to use document.documentElement rather than document.getElementsByTagName('html')[0]

This one, demonstrated here, hides <ul id="flash"> as completely and awesomely as the previous one. Simple!