patternModeratepending
Pattern: Progressive enhancement for resilient web apps
Viewed 0 times
progressive-enhancementfallbackresiliencesemantic-HTMLsupports
Problem
Apps built with JavaScript-first approach break completely when JS fails to load, is blocked, or errors out.
Solution
Build core functionality in HTML/CSS, enhance with JavaScript:
<!-- Form works without JS: -->
<form action="/search" method="GET">
<input name="q" type="search" />
<button type="submit">Search</button>
</form>
<!-- JS enhances with autocomplete: -->
<script>
const form = document.querySelector('form');
// Add autocomplete, prevent full page reload, etc.
</script>
.grid {
display: flex; flex-wrap: wrap; / Fallback /
}
@supports (display: grid) {
.grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); }
}
<img
src="photo-800.jpg"
srcset="photo-400.jpg 400w, photo-800.jpg 800w, photo-1600.jpg 1600w"
sizes="(max-width: 600px) 400px, 800px"
alt="Descriptive text"
loading="lazy"
/>
- Core content rendered as HTML (works immediately)
- JS hydrates for interactivity (enhances when loaded)
- If JS fails, content is still readable
Benefits:
- Core experience works without JS:
<!-- Form works without JS: -->
<form action="/search" method="GET">
<input name="q" type="search" />
<button type="submit">Search</button>
</form>
<!-- JS enhances with autocomplete: -->
<script>
const form = document.querySelector('form');
// Add autocomplete, prevent full page reload, etc.
</script>
- CSS features with fallbacks:
.grid {
display: flex; flex-wrap: wrap; / Fallback /
}
@supports (display: grid) {
.grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); }
}
- Image loading:
<img
src="photo-800.jpg"
srcset="photo-400.jpg 400w, photo-800.jpg 800w, photo-1600.jpg 1600w"
sizes="(max-width: 600px) 400px, 800px"
alt="Descriptive text"
loading="lazy"
/>
- Server-side rendering + hydration:
- Core content rendered as HTML (works immediately)
- JS hydrates for interactivity (enhances when loaded)
- If JS fails, content is still readable
Benefits:
- Works on slow connections (HTML loads first)
- Works with JS blocked (corporate firewalls, errors)
- Better SEO (content in HTML)
- Better accessibility (semantic HTML)
- Faster first paint (no JS needed for content)
Why
Progressive enhancement ensures your app works for everyone, then gets better for those with modern browsers and fast connections.
Revisions (0)
No revisions yet.