When building things with progressive enhancement, I often want the page styled a certain way when JavaScript is on vs off. When you use $(document).ready() in order to modify your page, you may end up watching the page modify before your very eyes, and if you’re like me, wish you could find a way around it.
For instance, I might have portions of a form hidden by default unless the user clicks an option to expand it. My old method was to show it all by default, then using $(document).ready(), hide those options. The problem is that I would see a flicker as elements start appearing then disappearing on my screen.
Now I use this method:
<body class="nojs">
<script>
var bodyEl = document.getElementsByTagName('body');
bodyEl[0].className = bodyEl[0].className.split('nojs').join(' jsEnabled ');
</script>
...
</body>
So by default, my page has a nojs class. And a script runs immediately after to remove that class, and to add in a ‘jsEnabled’ class in its place. I can then do things in my stylesheet like this:
.conditionalContent { display:none; } // what I really want to happen
.nojs .conditionalContent { display:block; } // in case JS is disabled
This accomplishes the same thing as I was trying to do above (keep an element hidden by default if JavaScript is disabled, but show it by default if JavaScript is disabled) but without the flicker.
And then you also have an option to make use of .jsEnabled class in the stylesheet as well.
If you happen to have jQuery pulled into your site in your <head>, you can use this instead:
<body class="nojs">
<script>
$('body').removeClass('nojs').addClass('jsEnabled');
</script>
...
</body>
If anyone’s discovered other methods of getting around this type of issue (like using Modernizr, or something else), I’d love to hear about it.
This is a really useful technique and is something I use on every site I develop. I have a slightly different syntax, which adds the
.jsclass to thehtmlelement instead of thebody. I also include this before I link to any CSS. Although this might not be allowed by the spec, it’s something that is completely supported. The syntax I use is below:document.getElementsByTagName('html')[0].className += ' js';You mention Modernizr, which does exactly the same thing as you and I describe — it adds a
.jsclass to thehtml(it also adds a plethora of other class names for you to hook on to). You include Modernizr in the head, someone gave me the following updated syntax, which only adds the.jsclass if Modernizr hasn’t already:if (typeof Modernizr === 'undefined') {var docElement = document.documentElement;
docElement.className = docElement.className.replace(/(^|\s)no-js(\s|$)/, ' js ');
};
The only thing I would question with regards to your solution, is the methodology of your CSS, instead of styling the
.nojs, I assume everything non-prefixed is with and without JavaScript, then I prefix the JavaScript-enabled styles with the new class..conditionalContent { display:block; } // default statehtml.js .conditionalContent { display:none; } // when JS is enabled
For me, this makes more sense. Firstly I think it follows the progressive enhancement idea (which I’m sure you’re doing) more closely). Secondly, it continues to work correctly if you don’t add the
.no-jsclass / JavaScript added class, which means you follow best practice of making sure everything works without JavaScript first, before enhancing the project with JavaScript.Let me know your thoughts.