Skip to content

Intro to progressive enhancement

Progressive enhancement is a development approach, not a technology choice. —What is progressive enhancement and why should you care?

Two rows of 4 frames: on top, a dissatisfied emoji above a single wheel, 2 wheels and an axle, and half of a car; finally, a satisfied emoji above a full car. In the second row, emojis growing slightly more satisfied above a skateboard, a scooter, a bike, and a motorbike.

This graphic was originally included in The power of progressive enhancement by Andy Bell.

The user's experience doesn't always have to look the same if it achieves the minimum viable product. A skateboard may be less efficient than a motorbike, but at least it gets you to the end goal -- you can't say the same about a single wheel.

Why should we do this?


While progressive enhancement doesn't necessarily mean building a no-JavaScript site, using this approach makes things more stable if something goes wrong. Don't think of the JS-less experience as only serving users who disable JS -- there are many times that JavaScript won't load. For more information, check out Everyone has JavaScript, right?


Older browsers may not get the exact same experience, but in the web, things are fluid and expecting the same pixel perfection across browsers is a fool's errand. Employing a progressive enhancement philosophy will help users in older browsers get a decent baseline experience.

Parallels in life

  • Escalator. When broken, you can still use them as stairs.
  • Electric toothbrush. When the charge is empty, you can still brush your teeth manually.
  • Moving sidewalks at the airport. When they aren't running, you can still walk on them manually.
  • Apple watch. If it's dead, you'd better hope you have another way to find the time!

All of these things (except the Apple watch) use electricity to enhance the experience, but they do not rely on it.

We can do the same with JavaScript and modern CSS.


Contrived, but relevant

Progressive grid

CSS grid has 95% browser support now, but that wasn't always the case. This Codepen uses a CSS feature query to lay out items in a two-column grid when supported; when unsupported, they'll simply stack on top of each other.

Progressive print button

It could be helpful to have a print button on a web page -- but why would we need to include it if the browser doesn't support print? Here we use JS to detect print support and dynamically inject the button when it's supported.


Quotes on geolanding pages (narrow viewports)

Enhanced experience, showing a single quote with a previous and next button to navigate to read other quotes Default experience, showing a single quote with a scrollbar to navigate to read other quotes

When JavaScript and IntersectionObserver are both supported, we add arrow buttons to allow the users to navigate through the quotes by clicking. When that's not the case, they can still read all of the quotes using a horizontal scrollbar.

Main business/category search

When JavaScript is disabled or fails to load, the user can still fill out the "Find" and "Near" fields to produce a page of search results, thanks to HTML form submission!

Customer review form

Enhanced experience, with a collapsed view by default

Enhanced experience, expanded view

Default experience, with all of the fields expanded

Progressive enhancement is employed in a few different ways here:

  • The form is collapsed when the page loads, so that the user has more visibility towards other parts of the page. Since the click-to-expand action requires JS, the default experience unfurls all of the fields.
  • The character count functionality requires JS, so when it is not available, the user will see a message reading "You can use up to 2000 characters." When JS is available, this changes to "2000 characters remaining" and counts down whenever the user types.
  • When JS is available, form validation is done without reloading the page. The user's focus moves to a section with all of the errors. When it's not, the page reloads with a list of all of the errors. The page's title is updated in both cases to note the error state so that the user is aware of the issues.
  • When enhanced, a cancel button lets the user collapse the form again. The cancel button is omitted in the default experience, because it would no longer do anything.