Courses/HTML & CSS/Progressive Enhancement

    Progressive Enhancement & Graceful Degradation

    Lesson 45 โ€ข Advanced Track

    What You'll Learn

    • Use @supports to detect CSS feature availability before applying styles
    • Build base experiences that work in all browsers without modern features
    • Layer enhancements for capable browsers using feature queries
    • Create no-JavaScript interactive components with HTML/CSS only
    • Understand the difference between progressive enhancement and graceful degradation
    • Apply the three-layer model: HTML (content) โ†’ CSS (style) โ†’ JS (behaviour)

    ๐Ÿ’ก Real-World Analogy

    Progressive enhancement is like an elevator in a building. Everyone can use the stairs (base experience). If the elevator works (modern browser), you get a smoother ride. The building is usable either way โ€” you never build a building that only works if the elevator is functioning.

    Understanding Progressive Enhancement

    Progressive enhancement is a web development philosophy that starts with the most basic, universally-supported experience and then adds layers of functionality for more capable browsers. It's the opposite of building a cutting-edge website and then trying to make it work in older browsers (graceful degradation).

    The core tool for progressive enhancement in CSS is the @supports rule (also called a feature query). It works like a media query but tests for CSS property support: @supports (display: grid) { ... } only applies the enclosed styles if the browser understands CSS Grid. This means you can write a flexbox fallback as the base and enhance with Grid where available.

    Beyond CSS, progressive enhancement also applies to HTML (using native elements like <details> and <dialog> that work without JS) and JavaScript (using feature detection before calling modern APIs). The goal is simple: no user should get a broken experience, regardless of their browser or device.

    1. @supports Feature Detection

    The @supports rule lets you wrap CSS in a feature check. If the browser doesn't support the feature, it ignores the entire block. The base styles outside @supports always apply.

    @supports Feature Detection

    Try it Yourself ยป
    Code Preview
    <!DOCTYPE html>
    <html><head><style>
    body { font-family: system-ui, sans-serif; padding: 24px; }
    h2 { color: #1565C0; }
    .card { padding: 24px; border: 1px solid #ddd; border-radius: 8px; margin: 16px 0; }
    .card h3 { margin-top: 0; color: #1565C0; }
    .btn { padding: 10px 20px; background: #1976D2; color: white; border: none; border-radius: 6px; font-weight: 600; cursor: pointer; }
    @supports (transition: all 0.3s) {
      .btn { transition: transform 0.2s, box-shadow 0.2s; }
      .btn:hover { transform: tr
    ...

    2. No-JavaScript Interactive Patterns

    HTML provides several interactive elements that work without any JavaScript: <details>/<summary> for accordions, radio inputs with CSS :checked for tabs, and <dialog> for modals. These are the foundation of progressive enhancement โ€” functionality that works even if JS fails to load.

    No-JS Accordion & Tabs

    Try it Yourself ยป
    Code Preview
    <!DOCTYPE html>
    <html><head><style>
    body { font-family: system-ui, sans-serif; padding: 24px; }
    h1 { color: #1565C0; }
    .accordion { border: 1px solid #ddd; border-radius: 8px; overflow: hidden; margin: 16px 0; }
    .accordion-item { border-bottom: 1px solid #ddd; }
    .accordion-item:last-child { border-bottom: none; }
    .accordion-item summary { padding: 16px 20px; cursor: pointer; font-weight: 600; background: #fafafa; transition: background 0.2s; list-style: none; display: flex; justify-content: spac
    ...

    3. Real-World @supports Patterns

    Three practical patterns: flexbox base enhanced with Grid, solid background enhanced with backdrop-filter glassmorphism, and standard inputs enhanced with :has() for parent-aware styling. Each provides a working base and a better experience where supported.

    Practical @supports Patterns

    Try it Yourself ยป
    Code Preview
    <!DOCTYPE html>
    <html><head><style>
    body { font-family: system-ui, sans-serif; padding: 24px; }
    h1 { color: #1565C0; }
    h2 { margin-top: 24px; }
    /* Base: works in ALL browsers */
    .grid { display: flex; flex-wrap: wrap; gap: 16px; margin: 16px 0; }
    .grid-item { flex: 1 1 250px; padding: 20px; background: #f5f5f5; border-radius: 8px; border: 1px solid #e0e0e0; }
    .grid-item h3 { margin-top: 0; }
    /* Enhancement: CSS Grid if supported */
    @supports (display: grid) {
      .grid { display: grid; grid-templa
    ...

    4. Progressive Enhancement vs Graceful Degradation

    These are two sides of the same coin. Progressive enhancement builds up from a working base; graceful degradation builds the full experience first and adds fallbacks. Modern best practice favours progressive enhancement because it ensures a working base experience is always guaranteed.

    PE vs GD Comparison

    Try it Yourself ยป
    Code Preview
    <!DOCTYPE html>
    <html><head><style>
    body { font-family: system-ui, sans-serif; padding: 24px; }
    h1 { color: #1565C0; }
    h2 { margin-top: 24px; }
    table { width: 100%; border-collapse: collapse; margin: 16px 0; }
    th, td { padding: 12px 16px; border: 1px solid #ddd; text-align: left; }
    th { background: #f5f5f5; }
    .arrow { color: #1976D2; font-weight: 700; }
    .layer { padding: 16px; border-radius: 8px; margin: 8px 0; }
    .layer-1 { background: #E3F2FD; border-left: 4px solid #1976D2; }
    .layer-2 { backgr
    ...

    When to Use Progressive Enhancement

    • Public-facing websites: You can't control what browser your visitors use. Always provide a base experience.
    • Using cutting-edge CSS: Wrap container queries, :has(), subgrid, and @layer in @supports blocks.
    • Markets with older devices: Developing regions often use older browsers. Progressive enhancement ensures access.
    • SEO-critical pages: Search engine crawlers may not execute JS. PE ensures content is always available in HTML.

    Common Mistakes

    • Building for Chrome only โ€” Always test in Safari and Firefox. @supports ensures safety across browsers.
    • Using cutting-edge features without fallback โ€” If the base experience breaks without the feature, it's not progressive enhancement โ€” it's a broken website.
    • Over-relying on JavaScript โ€” If a button only works with JS, it's not progressively enhanced. Use <a> tags or native form submissions as the base.
    • Not testing with JS disabled โ€” Try your site with JavaScript turned off. Core content and navigation should still work.
    • Confusing @supports with @media โ€” @supports checks feature support, not screen size. They serve different purposes but can be combined.
    • Ignoring the base layer โ€” Don't skip writing base styles just because @supports is available. The base must work standalone.

    ๐ŸŽ‰ Lesson Complete

    • โœ… @supports detects CSS feature support before applying styles
    • โœ… Write base CSS first that works everywhere, then enhance with @supports
    • โœ… HTML provides JS-free interactivity: details/summary, dialog, input:checked
    • โœ… Progressive enhancement = build up from a working base
    • โœ… Graceful degradation = build the ideal, add fallbacks for older browsers
    • โœ… The three-layer model: HTML (content) โ†’ CSS (presentation) โ†’ JS (behaviour)
    • โœ… Use feature detection, not browser detection (user-agent sniffing)
    • โœ… Next lesson: Custom Scrollbars for polished UI chrome

    Sign up for free to track which lessons you've completed and get learning reminders.

    Previous

    Cookie & Privacy Settings

    We use cookies to improve your experience, analyze traffic, and show personalized ads. You can manage your preferences below.

    By clicking "Accept All", you consent to our use of cookies for analytics and personalized advertising. You can customize your preferences or reject non-essential cookies.

    Privacy Policy โ€ข Terms of Service