Tell CSS that JavaScript is available ASAP

When you’re styling parts of a web page that will look and work differently depending on whether JavaScript is available or not, it can be very useful to use JavaScript to change or add a class name to the html element.

By doing this you can create CSS rules that will only be applied when JS is available and vice versa. The trick is to make sure the class names are switched as early as possible during page load.

The first thing to to is to give the html element a class name of no-js in the markup:

<html lang="en" class="no-js">

Next you need to use JavaScript to replace ”no-js” with ”js”. A simple way of doing this if you’re using jQuery is to add the following:

$(function() {
    $('html').addClass('js').removeClass('no-js');
});

However, there are some problems with that:

  • It won’t happen until the DOM is ready
  • jQuery needs to be downloaded and parsed first
  • You want this to run before any other scripts, so you’ll need to keep track of the source order of your script files

In many cases the switch will still be fast enough that you won’t notice anything, but if you’re doing some major restyling and the browser or download speed isn’t the fastest, you can end up with content visibly changing when the page loads. You probably don’t want that.

A concrete example is changing how a site’s top navigation works on a narrow display (most often a mobile phone). If you use something similar to what I decribe in An alternative to select elements as navigation in narrow viewports, the script may not have kicked in when the page is first displayed to the user, causing an annoying jump when the menu is re-rendered.

To avoid problems like that I have started adding the following tiny inline script straight after the title element, before anything else:

<script>
document.documentElement.className = document.documentElement.className.replace(/(\s|^)no-js(\s|$)/, '$1js$2');
</script>

This line simply replaces “no-js” with “js”. This could be reduced even further if you know for sure that the html element will never have any other class names in the markup:

<script>
document.documentElement.className = 'js';
</script>

I prefer the first of these options since you never know when another class name is going to show up when you work in teams with other people.

Either way, the class names will now be toggled when the CSS is loaded and applied. No waiting for things to be downloaded and parsed.

Going back to my example of adapting the top navigation for narrow viewports, if the html element has a “js” class you know that the navigation will be changed when that script is loaded and executed at some point after the DOM is ready. This means you can write your CSS accordingly to avoid (or at least reduce) redrawing and visual jumping.

Posted on September 20, 2012 in CSS, JavaScript

Comments are disabled for this post (read why), but if you have spotted an error or have additional info that you think should be in this post, feel free to contact me.