550

I notice that in a lot of template engines, in the HTML5 Boilerplate, in various frameworks and in plain php sites there is the no-js class added onto the <HTML> tag.

Why is this done? Is there some sort of default browser behavior that reacts to this class? Why include it always? Does that not render the class itself obsolete, if there is no no-"no-js" case and html can be addressed directly?

Here is an example from the HTML5 Boilerplate index.html:

<!--[if lt IE 7 ]> <html lang="en" class="no-js ie6"> <![endif]-->
<!--[if IE 7 ]>    <html lang="en" class="no-js ie7"> <![endif]-->
<!--[if IE 8 ]>    <html lang="en" class="no-js ie8"> <![endif]-->
<!--[if IE 9 ]>    <html lang="en" class="no-js ie9"> <![endif]-->
<!--[if (gt IE 9)|!(IE)]><!--> <html lang="en" class="no-js"> <!--<![endif]-->

As you can see, the <html> element will always have this class. Can someone explain why this is done so often?

Pranav 웃
  • 8,469
  • 6
  • 38
  • 48
Swader
  • 11,387
  • 14
  • 50
  • 84

7 Answers7

525

When Modernizr runs, it removes the "no-js" class and replaces it with "js". This is a way to apply different CSS rules depending on whether or not Javascript support is enabled.

See Modernizer's source code.

jmunsch
  • 22,771
  • 11
  • 93
  • 114
Gregory Pakosz
  • 69,011
  • 20
  • 139
  • 164
  • 6
    There's another great write-up on it here: http://www.alistapart.com/articles/taking-advantage-of-html5-and-css3-with-modernizr/ – Hannele Feb 28 '12 at 15:11
  • 51
    Since Modernizr replaces "no-js" with "js", you can use this as a way to do the equivalent of an if/else statement in your CSS code. For example, `.myclass { /* CSS code for all versions of your page goes here */ }`, `.js .myclass { /* This CSS code will only show up if JS is enabled */ }` and `.no-js .myclass { /* This CSS code will only show up if JS is disabled. */ }`. Hope this helps. -Nick – skcin7 Aug 22 '12 at 09:17
  • 2
    it's kind of annoying, because the html tag shouldn't have any class name assigned to it. – Ringo Aug 23 '12 at 20:21
  • 34
    @Ringo: HTML 5 specifies that *any* element may have a `class` attribute. Although HTML 4 technically doesn't, no browser chokes on it; even the ones that don't support it just ignore it, and i haven't seen one of those browsers in years. – cHao Nov 04 '12 at 23:16
  • 1
    wouldnt it be the same to add it to the tag and save trouble? – chesscov77 Nov 13 '13 at 01:05
  • @Juan that would potentially create *more* trouble. Using the class with `body` as opposed to any other element would be done differently: (`body.js` vs `.js p`). Also, as cHao pointed out, putting it on the body does not in fact save *any* trouble. – Zach Lysobey Jan 23 '14 at 15:15
  • @ZachL Huh? what's wrong with putting it on the body and using the same css code ( `.js p` ) – wired_in Mar 13 '14 at 23:14
  • @wired_in Imagine you want to add padding to the `` element. You would have to do `body.js{padding:...}` whereas any other element you can do `.js element {padding:...}` (`.js body...` will not work) It's a minor point, but it's just a little bit more consistent, and by extension, better. – Zach Lysobey Mar 13 '14 at 23:55
  • 4
    @ZachL I realize I must be smoking crack here, but it seems to me that `.js { padding: ...}` is just fine since you know as the one who implemented it that body = .js. More directly to your point, it seems you are claiming that `body.js` is worse than `.js body` which I am not following... – wired_in Mar 14 '14 at 07:46
  • @ZachL Furthermore, if your only argument is that every time you reference `.js` it should remain consistent and include a subclass or subelement like `.js element` you are acting like noone ever adds css to the `html` element. Think css resets and default styles, so the same logic applies there. I really am not seeing where you are coming from. As long as you know the root element is `body` there is no harm in this. Your only issue would be if you absolutely had to add styles to the `html` element and only when the `html` element had `.js` or `.no-js` – wired_in Mar 14 '14 at 08:04
  • @wired_in what added benefit to you get by putting it on `` instead? – Zach Lysobey Mar 14 '14 at 13:39
  • @ZachL I don't see any added benefit, but certainly there is nothing wrong with putting it on the `` like you were claiming. You get the same benefits as putting it on `` – wired_in Mar 14 '14 at 15:07
  • @ZachL It's not really a big deal, but putting the class attribute on the html tag would have a small benefit of being HTML<5 spec compliant. I'm not at all swayed one way or the other by any of the other arguments on the matter. – Hart Simha Jun 22 '14 at 18:09
  • 4
    It's worth mentioning html5-boilerplate puts it on `` and no issue has ever been reported against that. Somehow putting it on `` has become an established practice and people immediately know what it is and what it does. In the end, deviating from that practice just raises more questions. – Gregory Pakosz Jun 23 '14 at 08:36
  • That's a good point. Changing it *now* would create unnecessary problems with negligible benefit – Hart Simha Jun 24 '14 at 18:14
  • @cHao do you know what is `` mean ? – Shaiju T Sep 12 '16 at 14:36
  • 1
    @stom: It means the document element (basically the root node) has a class named "`default`". That's it. The browser doesn't care much about classes; they're to make scripts and stylesheets easier to use. The only changes to the functionality or appearance of the page, are the ones that your JS and/or CSS cause. – cHao Sep 16 '16 at 22:58
118

The no-js class is used by the Modernizr feature detection library. When Modernizr loads, it replaces no-js with js. If JavaScript is disabled, the class remains. This allows you to write CSS which easily targets either condition.

From Modernizrs' Anotated Source (no longer maintained):

Remove "no-js" class from element, if it exists: docElement.className=docElement.className.replace(/\bno-js\b/,'') + ' js';

Here is a blog post by Paul Irish describing this approach: http://www.paulirish.com/2009/avoiding-the-fouc-v3/


I like to do this same thing, but without Modernizr. I put the following <script> in the <head> to change the class to js if JavaScript is enabled. I prefer to use .replace("no-js","js") over the regex version because its a bit less cryptic and suits my needs.

<script>
    document.documentElement.className = 
       document.documentElement.className.replace("no-js","js");
</script>

Prior to this technique, I would generally just apply js-dependant styles directly with JavaScript. For example:

$('#someSelector').hide();
$('.otherStuff').css({'color' : 'blue'});

With the no-js trick, this can Now be done with css:

.js #someSelector {display: none;}
.otherStuff { color: blue; }
.no-js .otherStuff { color: green }

This is preferable because:

  • It loads faster with no FOUC (flash of unstyled content)
  • Separation of concerns, etc...
Zach Lysobey
  • 14,959
  • 20
  • 95
  • 149
  • 1
    The Modernizr version using a RegExp is safer (and likely faster) though. – AndrewF Aug 17 '13 at 20:22
  • @AndrewF - could you maybe expand on that a bit? How exactly is it safer? – Zach Lysobey Sep 05 '13 at 13:34
  • 12
    @ZachL The regexp version (with `\b`) doesn't match something like `anno-jsus`, the other changes it to `anjsus`. `no-js` is not a typical substring of any class name, but still in this respect it's "safer" with `\b`s. – Andras Nemeth Sep 22 '13 at 13:50
42

Modernizr.js will remove the no-js class.

This allows you to make CSS rules for .no-js something to apply them only if Javascript is disabled.

SLaks
  • 868,454
  • 176
  • 1,908
  • 1,964
17

The no-js class gets removed by a javascript script, so you can modify/display/hide things using css if js is disabled.

marc
  • 6,103
  • 1
  • 28
  • 33
  • You said "The no-js class gets removed by a javascript script". So how Javascript works (Able to remove 'no-js' class) if it 's disabled. Could you give me a clear? – haind Dec 26 '13 at 18:17
  • 2
    You're right and this is actually the point: If JavaScript is disabled, the class will stay and you can for example show some html part using CSS to warn the user about it. `.no-js #js-warning {display: block;}` – marc Jan 14 '14 at 12:39
  • Be aware, JS errors may occur after Modernizr has done this so its not a foolproof way of testing JS is functioning – experimenter Feb 11 '14 at 04:21
15

This is not only applicable in Modernizer. I see some site implement like below to check whether it has javascript support or not.

<body class="no-js">
    <script>document.body.classList.remove('no-js');</script>
    ...
</body>

If javascript support is there, then it will remove no-js class. Otherwise no-js will remain in the body tag. Then they control the styles in the css when no javascript support.

.no-js .some-class-name {

}
Fizer Khan
  • 88,237
  • 28
  • 143
  • 153
5

Look at the source code in Modernizer, this section:

// Change `no-js` to `js` (independently of the `enableClasses` option)
// Handle classPrefix on this too
if (Modernizr._config.enableJSClass) {
  var reJS = new RegExp('(^|\\s)' + classPrefix + 'no-js(\\s|$)');
  className = className.replace(reJS, '$1' + classPrefix + 'js$2');
}

So basically it search for classPrefix + no-js class and replace it with classPrefix + js.

And the use of that, is styling differently if JavaScript not running in the browser.

Alireza
  • 100,211
  • 27
  • 269
  • 172
1

The no-js class is used to style a webpage, dependent on whether the user has JS disabled or enabled in the browser.

As per the Modernizr docs:

no-js

By default, Modernizr will rewrite <html class="no-js"> to <html class="js">. This lets hide certain elements that should only be exposed in environments that execute JavaScript. If you want to disable this change, you can set enableJSClass to false in your config.

JSON C11
  • 11,272
  • 7
  • 78
  • 65