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

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.

Back to top