The CSS @supports at-rule
The CSS @supports at-rule applies CSS only when the browser supports a feature you test for, e.g. @supports (display: grid) { … }. These "feature queries" let you progressively enhance: give everyone a baseline, then layer on modern CSS where it works. Tests combine with and, or and not.
Overview
@supports asks the browser a yes/no question — "do you understand this CSS?" — and applies the block only if the answer is yes. You test a property and value together, like @supports (display: grid), and the styles inside run only where that pairing is supported.
This is the engine of progressive enhancement. Write a solid baseline that works everywhere, outside the query, then put the modern, not-universally-supported version inside an @supports block. Browsers that understand the feature get the upgrade; the rest keep the baseline, and nobody gets a broken layout.
The tests compose with and, or and not — @supports (gap: 1rem) and (display: flex), or @supports not (aspect-ratio: 1) for a fallback path. You can even test whether a selector is supported with @supports selector(:has(*)), which is handy as newer selectors roll out.
Syntax
/* baseline first, then enhance where supported */
.layout { display: block; }
@supports (display: grid) {
.layout { display: grid; gap: 1rem; }
}
@supports not (aspect-ratio: 1) {
/* fallback for older browsers */
}
Example
<style>
.grid { display: block; }
.grid div { background: #1c7ce9; color: #fff; padding: 16px; border-radius: 8px; text-align: center; margin-bottom: 8px; font: 600 13px system-ui, sans-serif; }
@supports (display: grid) {
.grid { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
.grid div { margin-bottom: 0; }
}
</style>
<div class="grid"><div>A</div><div>B</div></div>
Best practices
- Put a working baseline outside the query and the enhancement inside, so unsupported browsers still get a usable layout.
- Combine tests with
and,orandnotto target exactly the support you need. - Test the real property and value pair you intend to use — support can differ by value.
- Use
@supports selector(...)to feature-detect newer selectors like:has()before relying on them.
Frequently asked questions
What is a CSS feature query?
@supports that only applies when the browser supports the feature you test, e.g. @supports (display: grid) { … }.How do I check if a CSS feature is supported?
@supports (property: value) { … }. They apply only where that property and value are understood.How do I provide a fallback with @supports?
@supports not (feature) { … } to target browsers that lack the feature.Can @supports test selector support?
selector() function, e.g. @supports selector(:has(a)) { … }, which is useful for newer selectors.