Progressive Enhancement and JavaScript

A lot of people believe that progressive enhancement is not required and that they can build web sites that rely on JavaScript to generate their web pages. Now there are a very few types of web site where this is actually required in order for the site to function at all but most web sites could work without JavaScript (at least in some way) if they were designed appropriately.

The problem is that those people building most sites without progressive enhancement are completely mistaken in their thinking. They think that the number of people without JavaScript are such a small percentage that they can be ignored. By making this decision they have made a huge mistake with regard to JavaScript. They have assumed that a browser either has JavaScript enabled or it doesn't.

JavaScript is not a monolithic unchanging programming language where it is possible to treat it as if there were an on/off switch. While the number of people with JavaScript completely turned off might be very small, the number of people with it fully enabled is zero. Everyone is using a browser that partly supports JavaScript. Some browsers support more JavaScript than others but not even the latest development release of the most advanced browser supports all of the newest features proposed for JavaScript.

JavaScript is an evolving language and browsers evolve to support the new features added to the language. One of the reasons I am constantly telling people that the <noscript> tag is obsolete is that it implies that JavaScript is either on or off where in most cases that information is of no use to anyone whatsoever.

You shouldn't care whether JavaScript is on or off. That isn't the boundary condition for your particular JavaScript (unless your target browser is Netscape 2). Your boundary condition is determined by the JavaScript commands your script uses. If someone is using a browser that doesn't support all of the commands your script uses then they are on the off side of the boundary even though they have JavaScript enabled and would not see the content of a noscript tag.

If you limit yourself to the small portion of JavaScript that 99%+ of your visitors browsers support and include all the antiquated alternative code that some of those browsers need in place of modern JavaScript then you can rely on your script functioning in all of those current browsers. You can also rely on huge chunks of your code being completely obsolete and the script running far slower than necessary because of all the obsolete code it contains in a couple of years time.

Progressive Enhancement means future proofing your JavaScript. It has to do with writing your JavaScript in a way that prepares for the next generation of browsers rather than clogging up the system to provide support for long dead browsers. It means making a decision that certain browsers that don't support the best commands for performing what your script needs to do can either have those commands added via a polyfill until the browser actually catches up to the level of JavaScript that your script needs or that you decide that browsers that don't support those specific commands can make do without JavaScript and be treated as if JavaScript is off for those browsers. This of course means that your site needs to have some way (not necessarily a good way but a way) to function when you decide that the browser does not support enough JavaScript to make it worth providing the JavaScript to that browser.

By setting a minimum level of JavaScript that browsers need to support and providing polyfills for those few commands that your code can't do without but where too many of your current visitor's browsers don't yet support the command, we can write relatively modern JavaScript that will run far more efficiently in the more modern browsers than more antiquated code that doesn't need polyfills would. While this code may be less efficient in the browsers where the polyfill is needed, those browsers will eventually support the command and the polyfill can be removed leaving you with more modern code. This approach requires far less work in the future than writing code that the current browsers support and then having to rewrite it every couple of years to take advantage of the new commands that allow the code to run far more efficiently.

Even if you are not concerned with efficiency, there is the issue of maintenance of the code. The more modern your code is, the more easier your page is to maintain. Over the years the advances in JavaScript have made it easier and easier to make the scripts as unobtrusive as it is possible to make them. Scripts today can be written that only need something in the HTML to indicate what part (s) of the page they are supposed to interact with in order for them to work. You can attach the same script to thousands of pages without having to place any part of the script into the HTML. The scripts themselves can function completely independently of one another so that you can add and remove scripts without their breaking other scripts. Future versions of JavaScript will provide even further ways in which maintaining the scripts can be made easier and so keeping the scripts reasonably up to date will pay off in that far less work will be involved in maintaining web pages where the scripts are kept reasonably up to date (even including the work of updating the scripts) than would be involved in trying to maintain pages using antiquated code.

When writing scripts to attach to your web site now you need to decide what you are going to consider as the minimum level of JavaScript that a browser needs to support in order for you to deliver the JavaScript version and to give the HTML/CSS only version to those browsers that do not support that level of JavaScript.

In a talk that Christian Heilmann gave at the 2015 Microsoft Edge summit he suggested the following as a possible test for the browser probably being modern enough to run worthwhile JavaScript:

if ('querySelector' in document && 'localStorage' in window && 'addEventListener' in window) {
// script goes here

An alternative suggested by Jake Archibald is

if ('visibilityState' in document) {
// script goes here

This is referred to as 'cutting the mustard' or 'setting a baseline'. Whether you use one of these as your starting point or some other level of JavaScript support as your initial test you are drawing your own line as to what constitutes JavaScript support. Anyone using a browser that fails that test gets the plain HTML version of the page.

Now of course simply because a given browser supports those particular modern JavaScript commands doesn't necessarily mean it supports all of the other commands introduced around the same time and so your script will probably also need to test for any other equivalently modern commands that you are actually using in your code (or you may substitute the ones you actually use for those in the test).

Your script may also use progressive enhancement to make provision for newer browsers that support even newer commands that the current browsers don't yet support. They will then either be able to do things that the current browsers can't or if you include polyfills for those features you will be able to get it working in modern browsers and have it work even better in future browsers.

You will have far more time to consider the future direction of your script because you will not need to worry about legacy support for antiquated browser such as Konqueror 4 (only supports 92% of new commands introduced in 2011) or Firefox 31 (only supports 39% of new commands introduced in 2015) but can instead spend your time looking at ways to use the new commands to make your site even better.

Progressive enhancement is definitely a lot more than JavaScript enabled or not since as you can see the point where you consider JavaScript to be enabled ca vary depending on what level of JavaScript support you decide is the minimum you consider to be required in order to allow the script to run. For example if we were to use the visibilityState test then we treat anyone using Chrome 12, Firefox 9, Internet Explorer 9, Opera 11, or Safari 6 as not having JavaScript available and so present them with a version of the site without JavaScript. Of course we can't use a noscript tag to tell the people using those browsers that their browser doesn't support our JavaScript, we would need to embed any such message in the HTML and remove it with JavaScript.


This article written by Stephen Chapman, Felgall Pty Ltd.

go to top

FaceBook Follow
Twitter Follow