@supports Feature Queries
@supports lets you write CSS that only applies if the current browser actually understands a given property/value pair. It works exactly like a media query, except instead of testing the viewport it tests CSS feature support itself — making it the standard tool for progressively enhancing a page based on real capability rather than guessing from a user agent string.
Basic Syntax
@supports (display: grid) {
.layout {
display: grid;
}
}
@supports not (display: grid) {
.layout {
display: flex; /* fallback for browsers without grid */
}
}The condition inside the parentheses is a property/value pair, not just a property name — @supports (display: grid) checks specifically whether the browser supports grid as a value of display, which is important because a browser might support the display property in general while not supporting every value it can take.
Combining Conditions
Operator | Meaning | Example |
|---|---|---|
and | Both conditions must be supported | @supports (display: grid) and (gap: 1rem) |
or | Either condition being supported is enough | @supports (backdrop-filter: blur(4px)) or (-webkit-backdrop-filter: blur(4px)) |
not | Negates a condition | @supports not (display: grid) |
/* Require both features together */
@supports (display: grid) and (gap: 1rem) {
.grid {
display: grid;
gap: 1rem;
}
}
/* Accept either the standard or webkit-prefixed version */
@supports (backdrop-filter: blur(6px)) or
(-webkit-backdrop-filter: blur(6px)) {
.glass-panel {
-webkit-backdrop-filter: blur(6px);
backdrop-filter: blur(6px);
}
}Worked Example: Flexbox Fallback, Grid Enhancement
A common pattern is to write a Flexbox layout that works everywhere as the baseline, then override it with Grid only in browsers that support it — giving modern browsers the more powerful layout tool while older browsers still get a perfectly usable page.
/* Baseline: works in every browser, including ones without Grid */
.cards {
display: flex;
flex-wrap: wrap;
gap: 1rem;
}
.cards > .card {
flex: 1 1 240px;
}
/* Enhancement: only browsers that support Grid get this layout */
@supports (display: grid) {
.cards {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
}
.cards > .card {
flex: unset; /* no longer relevant once we're on Grid */
}
}Because the Flexbox rules are declared first and the @supports block comes after, browsers that don't understand @supports at all simply ignore the block they can't parse and keep the Flexbox layout — no explicit fallback logic required.