CSS @supports

Feature detection for progressive enhancement

πŸ” What is @supports?

The @supports rule allows you to check if a browser supports specific CSS features before applying styles. This enables progressive enhancement and graceful fallbacks for modern CSS features.


@supports (display: grid) {
  .container {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
  }
}
                                    

Output:

βœ… Grid is supported in this browser!

The grid styles will be applied.

Key @supports Features

βœ…

Feature Detection

Check if properties are supported

@supports (display: flex) {
  /* Flexbox styles */
}
πŸ”„

Progressive Enhancement

Add modern features safely

@supports (backdrop-filter: blur(10px)) {
  .modal { backdrop-filter: blur(10px); }
}
πŸ›‘οΈ

Graceful Fallbacks

Provide alternatives for older browsers

@supports not (display: grid) {
  .fallback { float: left; }
}
πŸ”—

Logical Operators

Combine multiple conditions

@supports (display: grid) and (gap: 20px) {
  /* Modern grid with gap */
}

πŸ”Ή Basic @supports Usage

Use @supports to apply CSS only when the browser supports specific features, ensuring graceful degradation. For example, @supports (display: grid) { .container { display: grid; } } applies grid layout only if supported. This prevents layout breaks in older browsers. Always pair with a fallback, like display: flex; or display: block;. Feature queries are essential for progressive enhancement, allowing you to use modern CSS while maintaining accessibility and functionality for all users.

/* Base styles for all browsers */
.layout {
  padding: 20px;
}

.item {
  margin-bottom: 20px;
  padding: 20px;
  background-color: #f0f0f0;
  border-radius: 4px;
}

/* Enhanced styles for Grid-supporting browsers */
@supports (display: grid) {
  .layout {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
    gap: 20px;
  }
  
  .item {
    margin-bottom: 0; /* Remove margin when using grid gap */
  }
}

Output:

Item 1
Item 2
Item 3

πŸ”Ή Logical Operators

βœ… Both display: grid and gap properties must be supported for the enhanced layout to activate, ensuring consistent spacing and structure. The @supports (display: grid) and (gap: 1em) query checks for this combined support. If either is missing, the browser uses a simpler fallback layout. This precise detection prevents partial, broken implementations and guarantees that users only experience the full grid design when their browser can render it correctly without visual flaws or misalignments.

/* AND operator - both features must be supported */
@supports (display: grid) and (gap: 20px) {
  .modern-grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 20px;
  }
}

/* OR operator - either feature can be supported */
@supports (display: flex) or (display: grid) {
  .flexible-layout {
    display: flex; /* Fallback to flex if grid not supported */
  }
}

/* NOT operator - apply when feature is NOT supported */
@supports not (display: grid) {
  .legacy-layout {
    float: left;
    width: 33.333%;
    box-sizing: border-box;
  }
}

Output:

Modern Grid
With Gap
Support

βœ… Both display: grid and gap are supported

πŸ”Ή Modern CSS Features Detection

This card uses backdrop-filter to create a frosted glass effect, but only if the browser supports it. The feature query @supports (backdrop-filter: blur(10px)) applies the effect conditionally. In unsupported browsers, a solid background fallback ensures readability. This technique demonstrates progressive enhancement: all users see a functional card, while modern browsers get an extra visual layer. It balances innovation with inclusivity, avoiding reliance on unstable features that could break the user experience.

/* Container Queries */
@supports (container-type: inline-size) {
  .card-container {
    container-type: inline-size;
  }
  
  @container (min-width: 300px) {
    .card { padding: 2rem; }
  }
}

/* CSS Subgrid */
@supports (grid-template-rows: subgrid) {
  .nested-grid {
    display: grid;
    grid-template-rows: subgrid;
  }
}

/* Backdrop Filter */
@supports (backdrop-filter: blur(10px)) {
  .glass-effect {
    backdrop-filter: blur(10px);
    background-color: rgba(255, 255, 255, 0.1);
  }
}

/* CSS Nesting */
@supports (selector(&)) {
  .component {
    color: blue;
    
    & .nested {
      color: red;
    }
  }
}

Output:

Glass Effect Card

This card uses backdrop-filter if supported by the browser.

πŸ”Ή Practical Example: Card Layout

The card layout is enhanced where supported with modern CSS features like Grid, Subgrid, and Container Queries. In capable browsers, cards use display: grid for complex internal alignment and container-type: inline-size for adaptive typography. Visual enhancements like backdrop-filter and smooth shadows are conditionally added. These improvements are layered over a solid, accessible base. The result is a future-friendly component that leverages the latest web platform innovations without sacrificing stability or accessibility.

/* Base styles - work in all browsers */
.card-grid {
  padding: 20px;
}

.card {
  margin-bottom: 20px;
  padding: 20px;
  background-color: white;
  border: 1px solid #ddd;
  border-radius: 8px;
  box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}

/* Enhanced with Flexbox */
@supports (display: flex) {
  .card-grid {
    display: flex;
    flex-wrap: wrap;
    gap: 20px;
  }
  
  .card {
    flex: 1 1 300px;
    margin-bottom: 0;
  }
}

/* Further enhanced with Grid */
@supports (display: grid) {
  .card-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  }
}

/* Add modern features if supported */
@supports (backdrop-filter: blur(10px)) {
  .card {
    backdrop-filter: blur(10px);
    background-color: rgba(255, 255, 255, 0.9);
  }
}

Output:

Card 1

Progressive enhancement in action

Card 2

Works across all browsers

Card 3

Enhanced where supported

🧠 Test Your Knowledge

What does @supports allow you to do?