Rethinking setting class=”js” to hide elements if JavaScript is available

by Michael Scharnagl

This article has been updated the last time on February 2, 2016 and the given information may be not accurate anymore. Feel free to contact me on twitter to get more details.

Last month a client reported an issue with their website, saying that the navigation isn’t working on his new iPhone 6s Plus. After getting all browser details, I started to reproduce the error, but neither on my iPad with an identical iOS and Safari version nor on any emulator on browserstack.com the error occurred. So, I arranged a meeting with the client and debugged directly on his smartphone. After some testing I noticed an JavaScript exception QUOTA_EXCEEDED_ERR:DOM Exception 22. I checked the code and found the error was caused by using localStorage.setItem();. While we checked if localStorage is available 'localStorage' in window we didn’t check for setItem(); properly and therefore our complete JavaScript failed.

This made me rethink my strategy of hiding elements when JavaScript is available. Typically I change the className of <html> from .no-js to .js in the <head> with JavaScript to avoid the FOUC. The problem with this method is if an error occurs, like described before, this will fail and probalby make parts of the site unusable.

Example

To demonstrate it here is an example of a responsive navigation.

Navigation on big screens
Navigation with JavaScript disabled/unusable
JavaScript usable and navigation closed
JavaScript usable and navigation open

If you view the demo on a small screen you can see that the navigation is hidden and the button to trigger the navigation is visible if JavaScript is usable. If JavaScript is disabled or unusable the navigation is hidden and the navigation is shown.

Here is the same demo with a JavaScript error added. As you can see in this case the navigation is displayed the same way it would be if JavaScript was disabled. So whatever error may stop your JavaScript from working the site will still be usable.

Conclusion

To avoid cases where JavaScript is available, but not usable I will use the following code in the future.

document.documentElement.className = document.documentElement.className.replace(/\bno-js\b/,'js');
window.onerror = function () {
  document.documentElement.className = document.documentElement.className.replace(/\bjs\b/,'no-js');
}

Additional I will use Cut the mustard to check for features.

if('querySelector' in document && 'addEventListener' in window) {
  // code here
} else {
  document.documentElement.className = document.documentElement.className.replace(/\bjs\b/,'no-js');
}

There are many ways where JavaScript is not available or executed in a browser and by using window.onerror we can handle them and show the same layout/functionality which would be shown for users who disabled JavaScript.

2 thoughts on “Rethinking setting class=”js” to hide elements if JavaScript is available

  1. Šime Vidas says:

    On the surface, allowing *any* window.onerror call to revert your page’s styling to “no-js” seems a bit excessive.

    • Michael says:

      Yes, it may be too much. I use the “js” class primarily for hiding content (off-site navigation, accordion…) and I want to be save and rather deliver the “no-js” version with everything visible and working than the “js” version where some parts may not work anymore.

Michael Scharnagl

Portrait Michael Scharnagl

Follow me: @justmarkup

Subscribe to RSS: /feed

A freelance front-end developer focusing on HTML5, CSS, progressive enhancement and web performance.