progressive-enhancement — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited progressive-enhancement (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
Canonical source:examples/PROGRESSIVE_ENHANCEMENT_BEST_PRACTICES.mdinmgifford/ACCESSIBILITY.mdThis skill is derived from that file. When in doubt, the example is authoritative.
Apply these rules when building any web feature or reviewing architecture decisions.
Start with a solid foundation that works for every user, then layer enhancements. Every user — regardless of browser capability, network speed, assistive technology, or JavaScript availability — must be able to access core content and complete core tasks.
Progressive enhancement is also a sustainability practice. Pages that work without JavaScript are dramatically lighter: fewer bytes transferred, less CPU spent on parsing and executing scripts, and less energy consumed per page view. See SUSTAINABILITY.md and the Web Sustainability Guidelines.
| Level | Meaning |
|---|---|
| Critical | Core content or task inaccessible without JS/CSS |
| Serious | Core content accessible but significantly degraded without JS/CSS |
| Moderate | Enhancement degrades gracefully but with friction |
| Minor | Best-practice gap; marginal impact |
Failure here is Critical.
Failure here is Moderate to Serious.
prefers-reduced-motion, prefers-color-scheme,prefers-contrast, forced-colors
JS that gates core content or tasks is Critical.
if ('fetch' in window && 'querySelector' in document) {
// apply enhanced experience
}Service Workers are a Layer 3 enhancement: they require JavaScript, are registered by a script, and must degrade gracefully when unavailable (private browsing, unsupported browsers, HTTPS not available).
When implemented, they extend both accessibility and sustainability:
low-income households, and developing regions) can continue to access previously loaded content offline
reducing data transfer and server energy per page view
// Register Service Worker only if supported — classic PE feature detection
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/sw.js').catch((err) => {
// Registration failure: page continues to work normally without it
console.warn('Service Worker registration failed:', err);
});
}Offline fallback pattern:
// sw.js — cache-first with network fallback
const CACHE_NAME = 'v1';
const OFFLINE_URL = '/offline.html';
self.addEventListener('install', (event) => {
event.waitUntil(
caches.open(CACHE_NAME).then((cache) =>
cache.addAll([OFFLINE_URL, '/', '/styles.css'])
)
);
});
self.addEventListener('fetch', (event) => {
if (event.request.mode === 'navigate') {
event.respondWith(
fetch(event.request).catch(() => caches.match(OFFLINE_URL))
);
}
});The offline fallback page (/offline.html) must itself be a valid Layer 1 HTML document — semantic, readable without CSS or JS.
Service Worker caching strategies (cache-first, network-first, stale-while- revalidate) should be chosen based on content update frequency. Avoid caching strategies that serve stale content for content that changes frequently without a cache-invalidation plan.
Rendering page content exclusively in JavaScript is Critical — users with JS disabled, AT users encountering compatibility issues, and low-bandwidth users are completely excluded.
Every byte of JavaScript that is not needed to access core content is unnecessary energy consumption. Prefer server rendering — it transfers HTML once; a JS bundle transfers code that must then be parsed, compiled, and executed on every visit.
<!-- Layer 1: works without JS -->
<form action="/search" method="get">
<label for="query">Search</label>
<input id="query" name="q" type="search">
<button type="submit">Search</button>
</form>Enhance with JS for instant results, autocomplete, or inline validation — while keeping the server-processed form as fallback.
A form that cannot be submitted without JS is Critical.
<!-- Layer 1: plain links always work -->
<nav aria-label="Main">
<ul>
<li><a href="/about">About</a></li>
<li><a href="/contact">Contact</a></li>
</ul>
</nav>Enhance with JS for dropdowns or animated transitions.
if ('fetch' in window) {
loadContentAsync(url);
} else {
// Standard link navigation works automatically
}Use aria-live regions only after confirming the base content is accessible without them.
prefers-reduced-motion, prefers-color-scheme, prefers-contrast, and forced-colors are Layer 2 responsibilities. Ignoring them is Moderate at minimum; ignoring prefers-reduced-motion for fast or flashing animations can reach Serious.
display:none / visibility:hidden on content required at the HTML layer — Criticaluser-scalable=no — Serious (prevents zoom for low-vision users)PE builds around their absence)
this is both an accessibility risk and a sustainability cost
prefers-reduced-motion, prefers-color-scheme, prefers-contrastNote: WCAG 4.1.1 Parsing was removed in WCAG 2.2 (August 2023). Modern browsers handle parsing errors uniformly. Valid semantic HTML remains important as a progressive enhancement foundation, but it is no longer a testable WCAG criterion. Do not cite it in audits or compliance statements.
Standards horizon: WCAG 3.0 is in development. No breaking changes to progressive enhancement principles are anticipated. Monitor: <https://www.w3.org/TR/wcag-3.0/>
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.