Table of Contents

Progressive Enhancement

Progressive enhancement starts with a working baseline and adds enhancements on top. This is the opposite of graceful degradation (which starts with the full experience and removes things when they fail).

The Principle

  1. Build the baseline so it works for everyone
  2. Layer enhancements for users with more capable environments
  3. Never require an enhancement for core functionality

Why It Matters

Most web developers build for a homogeneous user: latest device, latest OS, latest Chromium-based browser. This is hostile to:

Like all accessibility work, the result is a better experience for all users, not just the edge cases.

The .no-js Pattern

Start with no-js on the root element. Let JavaScript remove it if it runs:

<html lang="en" class="no-js">
// First script to run — removes the class if JS is available
document.documentElement.classList.remove('no-js');

This creates two automatic states:

Hiding JS-Dependent Elements

.no-js .js-required,
.no-js #theme-toggle,
.no-js .comments-section,
.no-js .post-graph {
  display: none !important;
}

Mark interactive elements in HTML:

<button class="theme-toggle js-required">Toggle theme</button>
<div class="post-graph js-required">...</div>

Explaining, Not Just Hiding

Hiding broken elements isn't enough — explain what's happening:

.no-js .status-container::after {
  content: "Status updates require JavaScript to be enabled.";
  font-style: italic;
  color: var(--muted);
  display: block;
  padding: 1rem;
}

The <noscript> Message

Four levels of no-JS messaging, from worst to best:

  1. Site breaks completely with no explanation ❌
  2. “You must enable JavaScript to continue” ❌
  3. “Some features require JavaScript” ✓
  4. Acknowledge the user's choice is valid, link to a dedicated page explaining what's missing and what alternatives exist ✓✓

Example of the best approach:

<noscript>
  <p>Welcome! I respect your decision to not use JavaScript.
     <a href="/no-js/">Learn more</a> about what's disabled and why.</p>
</noscript>

Style the noscript block so it's visible and friendly:

noscript {
  display: block;
  background: var(--panel);
  border: 1px solid var(--accent-primary);
  padding: 1rem;
  margin: 1rem 0;
  text-align: center;
  border-radius: 4px;
}

The /no-js/ Page

A dedicated page at /no-js/ documenting:

This is a resource for informed decision-making — which is the user's right.

See Also