Progressive enhancement is a technique that helps to ensure your software is robust and accessible. By following it, you can ensure as many people as possible will be able to use your website or app.

Start with a minimally viable version of your web design, and ensure it functions as necessary. Then, layer extra functionality and styling, so more capable browsers can benefit.

How Does Progressive Enhancement Work?

Because of its extremely distributed nature, the web has always needed to support a huge range of devices. From basic 1970s computers to capable modern desktops, tablets, and televisions, websites have come a long way.

At the heart of everything is HTML. As it’s a “forgiving” language, browsers will display HTML as well as they understand it. Typically, they’ll ignore anything they don’t support.

This can be useful from a developer’s point of view, but it can cause problems for readers. If your site displays a blank page when JavaScript cannot run, users have little choice but to abandon it. Progressive enhancement encourages you to deliver core content to everyone who can access it, then enhance that content using appropriate technologies, like CSS and JavaScript.

A Progressive Approach to Styling

CSS is the web’s style sheet language that you can use to customize colors, fonts, layouts, and many other visual aspects of your pages. You can use it to enhance the default look of your content, but that doesn’t mean you shouldn’t structure your content properly in the first place.

Take a menu bar, for example; you might structure it like this:

        <nav>
   <a href="/register">register</a>
   <a href="/login">log in</a>
   <a href="/about">about us</a>
   <a href="/contact">contact</a>
</nav>

To display a horizontal menu, with each link looking a bit like a button, you could style it using this CSS:

        nav a {
   text-decoration: none;
   display: inline-block;
   padding: 0.5em 1em;
   border: 1px solid;
   border-radius: 8px;
   margin-right: 1em;
}

When the browser fully renders this, it should look like the following:

A web browser displays a row of links styled as buttons, in a basic representation of a menu.

However, if CSS is unavailable, the menu will display like this:

A web browser displays a row of unstyled links with little space separating the text between them.

Notice how this doesn’t look anything like a menu and it’s not very easy to use since the links merge into one.

You can use an alternative structure to make the design more robust:

        <nav>
   <ul>
       <li><a href="/register">register</a></li>
       <li><a href="/login">log in</a></li>
       <li><a href="/about">about us</a></li>
       <li><a href="/contact">contact</a></li>
   </ul>
</nav>

Since this markup uses an unordered list element, it’s a lot more usable in the absence of CSS:

A web browser displays a bullet list unstyled links, in a basic representation of a menu.

Note how much easier it is to quickly scan and understand these links, even with the browser’s default styling. This approach will require you to add a bit more CSS, to override the default list styles:

        nav li { display: inline; }
    

Even though the final structure and styling are more complicated, and most users will have CSS enabled, this approach is more robust. It will be friendlier to users of screen readers and terminal-based browsers.

Introducing Functionality Progressively

Progressive enhancement is most important when it comes to the functioning of a site or app. The principle states that, no matter what, your website should function as well as possible.

In practice, this typically applies to JavaScript. If you introduce client-side behavior, it should layer functionality on top of a site or application that already works without it.

A very common case is event handling. Imagine a page that loads additional content on demand. This could be a manual infinite scroll, a comment embed, or similar.

        <body>
   <!-- ... -->
   <button onclick="load_more();">
       Load More
   </button>
   <!-- ... -->
</body>

​​​​​​​The button’s onclick attribute contains JavaScript code that will run when somebody clicks the button. However, if JavaScript is unavailable, this button will do nothing. A user will be left clicking this button with no feedback and no idea of what is going wrong. A far better approach uses progressive enhancement:

        <body>
    <!-- ... -->
    <a id="p2" href="/page/2">Page 2</a>

    <script>
   function load_more() { console.log("!"); }

    /* Replace link with button */
    var link = document.getElementById("p2");
    var button = document.createElement("button");
    button.innerText = "Load More";
    button.addEventListener("click", load_more);
    document.body.insertBefore(button, link);
    link.parentNode.removeChild(link);
    </script>
</body>

This code transforms the basic link into a button with an event handler. By introducing the dependency on JavaScript using JavaScript itself, you can be certain it will work. And there’s a functional default behavior that works, in the form of the standard link to /page/2.

Is Progressive Enhancement Really Necessary?

Everyone uses browsers with CSS and JavaScript, so why bother catering for a situation that doesn’t arise? Well, there are several reasons you should adopt the good practice of progressive enhancement.

  1. First, not everyone that visits your website is using a browser. Some visitors will be bots, like a search engine indexer, and these may not understand CSS or JavaScript at all.
  2. Second, not every person who visits your site will use a browser with CSS and JavaScript. Some visitors may use a terminal-based browser, which displays plain text with minimal formatting. Others may use a screen reader.
  3. Third, even if a browser supports CSS and JavaScript, things go wrong. A broken link or bad network connection may result in a missing .css or .js file. A bug in JavaScript may cause other code to not run at all.
  4. Finally, some visitors may actively decide to disable CSS or JavaScript. They may do so out of privacy concerns or because they’re on a slow or pay-by-use connection.

A Progressive Mindset Works Wonders

Above all, progressive enhancement encourages you to adopt a content-first approach. Content is king, so your text and images should always be available, for everyone, however they’re accessing your site.

By giving all readers the best experience possible, then making it even better for those who can benefit, you can have the best of all worlds. Progressive enhancement is just one key component of good accessibility and usability practice.