In defence of graceful degradation and where progressive enhancement comes in

The concept of graceful degradation predates the web. It describes a way to design fault tolerant systems:

“The ability of maintaining functionality when portions of a system break down is referred to as graceful degradation.”—Wikipedia

And although we strive to design resilient digital experiences, we’ve come to view graceful degradation as the wrong way to do it.

In the context of the web, graceful degradation has become a bit of a dirty word and I think that’s a problem.

Because building shared knowledge first requires us to use shared language. If we start to misrepresent concepts in how we define them, there’s a risk we’ll apply them incorrectly too.

In this article, I’ll explain how I think graceful degradation has come to earn its bad rep, and why I believe it’s time to rethink it.

What is graceful degradation?

Escalators are a good example of graceful degradation—when they break down, they become steps.

Similarly, HTML and CSS are also designed to degrade gracefully when things go wrong:

“The loose error‐handling of HTML and CSS means that many authoring mistakes or browser support issues are handled gracefully; the browser simply ignores what it doesn’t understand and carries on.”—Jeremy Keith, Resilient Web Design

When, for example, a browser doesn’t support the <video> element, it renders the content inside the element and continues parsing the rest of the HTML without a problem.

<video>
  Put transcript and images in here instead.
</video>

This gives us an easy way to provide a fallback for users with less capable browsers.

The same goes for CSS:

div { border-radius: 3px;  background-colour: blue }

If a browser doesn’t support border-radius, the browser will simply skip it and use angled corners instead.

HTML and CSS degrade gracefully by design. All we need to do is use them and we get resilience for free. That’s why the web is such a success.

But graceful degradation is often thought of as bad—especially when compared with its close relative, progressive enhancement.

Why people think graceful degradation is bad and progressive enhancement is good

For an understanding of why graceful degradation is often painted in an unflattering light, we can look to some of the common definitions.

Graceful degradation is just progressive enhancement in reverse

MDN, for example, describes graceful degradation as designing an optimised experienced first, and working backwards to consider how to make things work for less capable browsers:

“Graceful degradation […] centers around trying to build a modern web site/application that will work in the newest browsers, but fall back to an experience that while not as good still delivers essential content and functionality in older browsers.”

Progressive enhancement, MDN says, is “seen as going in the opposite direction to graceful degradation”.

With progressive enhancement, we start with a baseline experience that works for everyone, and enhance the experience where possible for people using better browsers.

The implication here is that the order of events affects the outcome: if you start with the optimised experience, the baseline becomes an afterthought.

As Aaron Gustafson puts it:

“[with graceful degradation] older browsers are expected to have a poor, but passable experience. […] Because they are not the focus, little attention is paid beyond fixing the most egregious errors.”

Theoretically we may still end up in exactly the same place, but whether we start with the basic experience or the enhanced one by default is considered synonymous with our priorities.

If you prioritise everyone, then you’re good. If you prioritise the privileged few who use the latest browsers then you’re bad.

And I agree, that is bad. I just don’t think this should be attributed to graceful degradation.

Graceful degradation is making users aware of a shortcoming

W3 states that:

“[Graceful degradation is] providing an alternative version of your functionality or making the user aware of shortcomings of a product as a safety measure to ensure that the product is usable.”

Both graceful degradation and progressive enhancement provide alternative versions when things fail, which means that while this part of the definition is true, it’s not specific to graceful degradation.

But what about making users aware of a shortcoming?

It’s true that making users aware of a shortcoming is usually unhelpful and unnecessary. But attributing this approach to graceful degradation is part of what causes people to think it’s bad.

I’ll explain with a common example—the one W3 uses to demonstrate graceful degradation in relation to letting users print a web page.

Here’s the pertinent code:

<a href="javascript:window.print()">Print</a>
<noscript>
  <p>Turn on JavaScript to print.</p>
</noscript>

When JavaScript is enabled, clicking the link calls window.print() which prints the web page. But when JavaScript is disabled, clicking the link does nothing, and the user sees the message inside the <noscript> element.

This is problematic because:

  • The user is provided with a print button that does nothing when clicked, which results in a broken experience.
  • The user sees a message about the lack of support and workaround. But the user may not be able to use the workaround, and the browser might not be able to run JavaScript.
  • Even if the user has JavaScript turned on, the browser might block the script or not recognise the code.

This is why the <noscript> element is fragile and not recommended. It doesn’t create an alternative, degraded experience—it creates a broken one.

Instead, the print button should be injected into the page when the browser supports window.print(). This is known as feature detection and is covered by part of W3’s definition of progressive enhancement:

“Starting with a baseline of usable functionality, then increasing the richness of the user experience step by step by testing for support for enhancements before applying them”

Given W3’s fragile example of how to let users print—and the fact they’re calling it graceful degradation—it’s no wonder that some people think progressive enhancement is good and graceful degradation is bad.

With progressive enhancement, users are only ever given a working print button on the page, when the browser is able to do so.

As there’s no equivalent solution to printing a page without JavaScript, the degraded experience isn’t equitable, and it certainly isn’t graceful.

But crucially, none of this means that graceful degradation is bad.

The <noscript> element is just not an appropriate way to cover the something-went-wrong-with-JavaScript problem. Progressive enhancement—that is, feature detection—is the only way to do that.

Progressive enhancement makes JavaScript degrade gracefully

HTML and CSS are declarative languages. You declare how you want something to be and then the browser does its best to apply them.

JavaScript is an imperative language. When you write a script, all of it needs to run in order for it to work. A program would be very hard to debug if you made a mistake and it didn’t tell you.

The problem is that, unlike HTML and CSS, if you give a browser some badly-formed JavaScript or try to use an unsupported method, not only will the browser throw an error, it will stop parsing the script and refuse to go any further.

To solve this problem we have to:

  • Create a baseline experience using HTML and CSS that all users get. This becomes the fallback users get when the JavaScript enhancement fails.
  • Use feature detection to check the browser supports the JavaScript methods before using them as an enhancement. This stops browsers throwing an error half way through resulting in a broken experience.

This is progressive enhancement. An approach to making interfaces that ensures JavaScript degrades gracefully—something that HTML and CSS do automatically.

So graceful degradation isn’t in opposition with progressive enhancement at all.

In conclusion

Graceful degradation is an integral part of designing resilient, fault-tolerant systems.

Despite the common narrative, graceful degradation is not in competition with progressive enhancement—it’s simply an approach that makes JavaScript degrade gracefully, like HTML and CSS do by default.

Graceful degradation and progressive enhancement have the same objective—to create robust, accessible and broad-reaching solutions that work for everyone no matter their choice of browser.

And that’s a very good thing indeed.

Huge thanks to Amy Hupe who paired with me on this from start to finished. And distilled this difficult message down to its irreducible core. If it wasn’t for her, I’d have either made a total mess of it, or worse, binned it altogether. 🙌