← Home ← Codex ← DEBT
Browse by Category
+ added · updated 7d
← Back to glossary

Progressive Enhancement

Frontend Intermediate
debt(d5/e7/b7/t5)
d5 Detectability Operational debt — how invisible misuse is to your safety net

Closest to 'specialist tool catches' (d5) — Lighthouse and axe can flag JS-only content, missing semantic HTML, and accessibility issues, but they don't catch every progressive-enhancement violation; some issues only surface when JS is disabled or fails to load.

e7 Effort Remediation debt — work required to fix once spotted

Closest to 'cross-cutting refactor across the codebase' (e7) — retrofitting PE means rewriting forms to POST natively, restructuring SPA routes to have server-rendered equivalents, and adding HTML fallbacks across many components; the quick_fix describes rebuilding the rendering pipeline (PHP renders semantic HTML first), not a localized change.

b7 Burden Structural debt — long-term weight of choosing wrong

Closest to 'strong gravitational pull' (b7) — committing to PE shapes every feature: backend must render meaningful HTML, JS must layer on top, every interaction needs a no-JS path. It applies to all web contexts and influences architecture choices broadly without fully defining the system shape.

t5 Trap Cognitive debt — how counter-intuitive correct behaviour is

Closest to 'notable trap most devs eventually learn' (t5) — the misconception (that PE means supporting no-JS users specifically, rather than starting from an HTML foundation that's then enhanced) is a documented gotcha; developers commonly assume modern SPAs are exempt when SSR-based PE is still viable.

About DEBT scoring →

Also Known As

graceful degradation progressive enhancement no-JS fallback

TL;DR

Building web experiences in layers — semantic HTML baseline, CSS styling, JavaScript enhancement — ensuring core functionality works without JavaScript.

Explanation

Progressive enhancement starts with a functional HTML foundation (forms that POST, links that navigate, semantic structure). CSS adds visual polish. JavaScript adds interactivity, but the page works without it. Contrast with graceful degradation (start rich, degrade). Benefits: works for users with disabled JS (corporate firewalls, accessibility tools), faster initial page load (HTML renders before JS parses), better SEO (crawlers see real content), and resilience to JS errors. PHP apps naturally support progressive enhancement — server-rendered HTML is the baseline.

Common Misconception

Progressive enhancement means building for users without JavaScript — it means starting from a solid HTML foundation that works, then enhancing with JS; modern JS apps can still use this approach with server-side rendering.

Why It Matters

A form that only works via JavaScript fails for users with slow connections where JS hasn't loaded, users behind restrictive corporate proxies, and screen reader users who navigate without enabling JS.

Common Mistakes

  • onClick for navigation without href — <button onclick=navigate()> breaks keyboard nav, bookmarking, and no-JS.
  • Search forms that only work with JS — POST to /search should work as a native HTML form.
  • Critical content rendered only by JavaScript — invisible to search engines and slow-connection users.
  • AJAX-only forms with no server-rendered fallback.

Code Examples

✗ Vulnerable
<!-- JavaScript-only form — broken without JS:
<form id="search">
    <input id="q" type="text">
    <button onclick="doSearch()">Search</button>
</form>
<div id="results"></div>
<script>
function doSearch() {
    fetch('/api/search?q=' + document.getElementById('q').value)
        .then(r => r.json()).then(renderResults);
}
</script>
✓ Fixed
<!-- Works without JS (POST to server), enhanced with JS:
<form action="/search" method="GET" id="search">
    <input name="q" type="search" value="<?= esc($q) ?>">
    <button type="submit">Search</button>
</form>
<div id="results">
    <!-- Server-rendered results here -->
    <?php foreach ($results as $r): ?>
        <article>...</article>
    <?php endforeach; ?>
</div>
<script>
// Enhancement: AJAX search without page reload
document.getElementById('search').addEventListener('submit', async e => {
    e.preventDefault(); // Override default only if JS works
    // ... AJAX update
});
</script>

Added 16 Mar 2026
Edited 22 Mar 2026
Views 60
Rate this term
No ratings yet
🤖 AI Guestbook educational data only
| |
Last 30 days
0 pings T 0 pings W 1 ping T 1 ping F 1 ping S 0 pings S 0 pings M 0 pings T 0 pings W 0 pings T 3 pings F 3 pings S 4 pings S 1 ping M 1 ping T 2 pings W 1 ping T 0 pings F 0 pings S 0 pings S 0 pings M 1 ping T 0 pings W 0 pings T 0 pings F 1 ping S 0 pings S 1 ping M 0 pings T 0 pings W
No pings yet today
No pings yesterday
Scrapy 11 Amazonbot 9 Perplexity 7 Ahrefs 4 Google 3 ChatGPT 3 SEMrush 3 Unknown AI 2 Claude 1 Meta AI 1 Bing 1 PetalBot 1
crawler 44 crawler_json 2
DEV INTEL Tools & Severity
🟡 Medium ⚙ Fix effort: High
⚡ Quick Fix
Build the core experience in semantic HTML first (PHP renders it), add CSS for visual enhancement, then add JavaScript for rich interactions — the content works without CSS or JS
📦 Applies To
any web
🔗 Prerequisites
🔍 Detection Hints
Page blank or broken without JavaScript; PHP rendering JSON not HTML requiring JS to display; content inaccessible to search engines or screen readers
Auto-detectable: ✓ Yes lighthouse axe w3c-validator
⚠ Related Problems
🤖 AI Agent
Confidence: Medium False Positives: Medium ✗ Manual fix Fix: Medium Context: File Tests: Update


✓ schema.org compliant