References

Beginner-friendly references for web development, with live, editable examples.

The CSS @supports at-rule

At-rule CSS All modern browsers Updated
Quick answer

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

Live 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, or and not to 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?
A block of CSS guarded by @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?
Wrap the styles in @supports (property: value) { … }. They apply only where that property and value are understood.
How do I provide a fallback with @supports?
Write the baseline outside the query, or use @supports not (feature) { … } to target browsers that lack the feature.
Can @supports test selector support?
Yes, with the selector() function, e.g. @supports selector(:has(a)) { … }, which is useful for newer selectors.