The Case for Progressive Enhancement
Progressive enhancement has a branding problem. Say the phrase and half your audience hears "build websites like it's 2008," as if the technique were a diet of hand-written HTML and denial. That's a shame, because underneath the retro reputation is one of the sharpest pieces of engineering risk management the web has ever produced — and the conditions that made it valuable haven't gone away. If anything, they've gotten worse.
Here's the argument, made fresh for the current landscape, plus the practical patterns that make it cheap to adopt.
What progressive enhancement actually claims
Strip the ideology and the claim is simple: build in layers, and make each layer work without the one above it.
- HTML carries the content and core function. A reader can read; a form can submit; a link can navigate.
- CSS makes it pleasant. If it fails to load, the page is ugly but usable.
- JavaScript makes it delightful — instant validation, smooth transitions, live updates. If it fails, you fall back to the layer below, which still works.
The inverse approach — JavaScript-first, where the HTML is an empty shell and everything meaningful is assembled in the browser — collapses the layers into one. When the top layer fails, there is no layer below. You don't degrade; you disappear.
"But everyone has JavaScript now" — the objection, examined
The standard objection is that users who disable JavaScript are a rounding error, so designing for its absence is designing for ghosts. The objection is aimed at the wrong target. Progressive enhancement was never mainly about users who turn JavaScript off. It's about the far larger population for whom JavaScript fails or hasn't arrived yet:
- The network drops mid-load. The HTML arrived; the 400 KB bundle didn't. On trains, in elevators, on hotel Wi-Fi, this is a daily event, not an edge case.
- A third-party script errors and takes your code with it. One unhandled exception from an ad script or an overzealous tag manager can halt execution before your app boots.
- Corporate firewalls and content blockers strip or mangle scripts. Ad-blocker usage sits somewhere in the range of a quarter to a third of desktop users, and blockers increasingly break non-ad scripts as collateral damage.
- A CDN region hiccups and your script host is unreachable for ninety seconds. Your HTML, served from elsewhere, was fine the whole time.
- The interval before the bundle parses. Every visitor is a no-JavaScript user for the first seconds of every page load. On a mid-range phone over cellular, that window is long enough to read your headline and try to tap something. A JavaScript-dependent page is inert during exactly the moments that shape first impressions.
A useful rule of thumb from the resilience literature: the question isn't whether your JavaScript will fail for some visitors this month — at any real traffic volume, it will — but what those visitors get when it does. Progressive enhancement's answer: a working site. The alternative's answer: a blank rectangle.
What's changed by 2026 — mostly in PE's favor
The trade-off used to be real: build resilient and forfeit rich interactions, or build rich and accept fragility. The platform has spent a decade dissolving that trade-off.
The browser does more without your help
A remarkable amount of what once required JavaScript is now declarative:
<details>/<summary>— accordions with zero script.<dialog>— real modals, focus management included.- The Popover API — tooltips, menus, and overlays in HTML attributes.
- CSS
scroll-snap,position: sticky, container queries,:has()— layouts and carousel-like patterns that used to demand libraries. - Native form validation with
required,pattern, and input types. - View transitions for smooth page-to-page animation — including across full page loads in modern browsers, which means classic multi-page sites can feel "app-like" with no client-side router at all.
Every one of these is a feature you previously bought with fragile JavaScript and now get from the platform, with accessibility mostly handled. The zero-JS baseline of today is dramatically richer than the zero-JS baseline the objections were formed against.
The frameworks quietly conceded
Watch what the framework world ships rather than what it argues: server-side rendering as the default, server components, islands architectures that hydrate only interactive fragments, form actions that work before hydration. The mainstream JavaScript ecosystem has spent years rediscovering, feature by feature, that meaningful HTML from the server plus selective enhancement is the architecture that works. They don't call it progressive enhancement. It's progressive enhancement.
The compounding side benefits
Layered construction pays dividends beyond failure handling, and they're worth naming because they often justify the approach on their own:
- SEO without hostage negotiation. Content that exists in the HTML is content every crawler, preview-card generator, and AI answer engine can read without executing anything. Rendering-dependent content gets indexed eventually, usually, mostly — "eventually, usually, mostly" is a bad foundation for a traffic strategy.
- Accessibility falls out for free-ish. The HTML layer forces you to use real buttons, real links, real form labels — the exact semantics assistive technology needs. Sites built as div-soup and retrofitted with ARIA almost always end up less accessible than sites whose baseline layer was honest HTML.
- Performance floor. The HTML layer paints fast because it doesn't wait for a bundle. Enhancement is additive, so your worst-case experience is "fast and plain" rather than "slow and broken."
- Longevity. HTML and CSS from fifteen years ago still render. JavaScript stacks from five years ago frequently don't build. The lower layers of your site are the ones that survive framework churn.
How to actually practice it (without abandoning your tools)
Progressive enhancement is a discipline, not a technology choice. You can practice it in WordPress, in a modern framework, or in hand-rolled HTML. The habits:
Start every feature with the question: what's the HTML version?
- A search filter? The HTML version is a form that submits and returns a filtered results page. Enhance with instant client-side filtering.
- An infinite scroll? The HTML version is a "Next page" link. Enhance by intercepting it and appending results.
- A like button? The HTML version is a form posting to an endpoint. Enhance with an optimistic in-place update.
Notice the pattern: the enhanced version intercepts the baseline rather than replacing it. If the interceptor never loads, the baseline still works. This is usually a modest amount of extra thought, not double the work — the server endpoint has to exist either way.
Use real elements
Buttons are <button>. Navigation is <a href>. Data entry is a <form>. A div with a click handler is a promise that your JavaScript will always load, made silently, to every visitor.
Feature-detect, never assume
Enhance conditionally: check for the API before using it, wrap enhancements so one failure doesn't cascade, and let CSS @supports gate newer layout features with sensible fallbacks. Modern browsers make graceful partial support easy — take the offer.
Test the layers occasionally
Once a quarter, load your critical pages with JavaScript disabled (DevTools makes this a checkbox) and with network throttling set to slow 3G. You're not aiming for perfection in that state; you're checking that the checkout can complete, the contact form submits, and the content reads. Twenty minutes, quarterly, is the whole tax.
Where the strict version genuinely doesn't fit
Fairness requires the counter-case. Some products have no meaningful HTML baseline: collaborative whiteboards, video editors, real-time dashboards, games. The "non-JavaScript version" of Figma is a screenshot. For genuinely app-class software, demand JavaScript openly — but say so with a clear message rather than a silent blank page, and keep the marketing site, docs, and login flow (things that do have an HTML baseline) resilient anyway.
The trap is flattery: most sites that consider themselves app-class are content sites with a few interactive widgets. A store, a blog with comments, a booking page, a member portal — every one of these has an obvious HTML baseline. If your site's core verbs are read, browse, submit, buy, you're in progressive enhancement territory, whatever your stack.
The bet you're actually making
Every architecture is a bet. JavaScript-first bets that networks are reliable, third parties are well-behaved, devices are fast, and bundles always arrive — and pays out a marginally simpler development model if it wins. Progressive enhancement bets that things fail — and pays out a site that works anyway, plus better SEO, better accessibility, a faster first paint, and markup that outlives your framework.
One of those bets loses catastrophically and loses often. The other loses a little politeness in the worst case. Today, with the platform's baseline richer than it has ever been, the resilient bet has never been cheaper to place.