@supports Feature Queries
Progressively enhance with @supports — detect properties, selectors, and font tech, and structure fallbacks that still look intentional.
- css
- supports
- feature-queries
@supports is a feature query: apply CSS only when the engine claims to support a given property/value, selector, or condition. It is the CSS cousin of capability detection — better than UA sniffing for progressive enhancement.
Docs: MDN @supports, feature queries guide.
Basic property checks
.card {
background: #f4f0ea; /* fallback */
}
@supports (background: color-mix(in srgb, red, blue)) {
.card {
background: color-mix(in srgb, var(--brand) 12%, white);
}
}
@supports (backdrop-filter: blur(4px)) {
.topbar {
background: rgb(255 255 255 / 0.7);
backdrop-filter: blur(12px);
}
}
Selector support
@supports selector(:has(*)) {
.card:has(img) {
padding: 0;
}
}
Useful for :has(), nesting-related selectors, and other newer selector features.
Logical operators
@supports (display: grid) and (gap: 1rem) {
.layout {
display: grid;
gap: 1rem;
}
}
@supports not (display: grid) {
.layout {
display: flex;
flex-wrap: wrap;
}
}
@supports (display: grid) or (display: -ms-grid) {
/* historical patterns; prefer modern checks */
}
Fonts and tech
@supports (font-variation-settings: normal) {
body {
font-family: "InterVariable", system-ui, sans-serif;
font-optical-sizing: auto;
}
}
@supports (font-tech(color-COLRv1)) {
/* color font enhancements */
}
Structure fallbacks intentionally
Order matters: baseline first, enhancement inside @supports.
.grid {
display: flex;
flex-wrap: wrap;
gap: 1rem;
}
.grid > * {
flex: 1 1 16rem;
}
@supports (grid-template-columns: subgrid) {
/* optional advanced path */
}
Don’t leave unsupported browsers with display: grid tracks that break because you only set modern values.
@supports vs @media
| At-rule | Question |
|---|---|
@media |
What’s the environment (width, preference, print)? |
@supports |
What can this CSS engine parse/apply? |
They nest freely:
@media (min-width: 48rem) {
@supports (display: grid) {
.page {
display: grid;
grid-template-columns: 14rem 1fr;
}
}
}
Interview out-loud
“@supports applies rules when a feature is supported — properties, values, or selectors. I write a solid baseline first, then enhance inside feature queries. I use not/and/or for compound checks and I don’t confuse feature queries with media queries.”
Footguns
- Checking a property that all target browsers already support — noise.
- False confidence:
@supportscan pass while a sub-feature is buggy. - Empty baseline relying only on supported path.
- Detecting with JS when CSS
@supportswould suffice for pure style forks. - Over-nesting until cascade ownership is unclear.
Pairing with @media and @layer
@layer components {
.panel {
display: flex;
flex-direction: column;
gap: 1rem;
}
@supports (grid-template-rows: subgrid) {
@media (min-width: 48rem) {
.panel {
display: grid;
/* advanced path */
}
}
}
}
Feature queries do not protect you from bugs inside a supported property. Still keep visual QA. For JS feature detection that must match CSS, consider dual checks carefully — CSS @supports and CSS.supports() should use the same condition string when possible.
False friends
A browser may claim support for display: grid while shipping incomplete subgrid, or support gap in flex only after a certain version. Feature queries are coarse. Structure enhancements so incomplete support still yields usable layout — not a broken halfway grid. When a bug is engine-specific, a targeted @supports plus a code comment with the bug link is kinder than user-agent sniffing.
Related
Further reading
Related guides
- Accent Color and Form ControlsUse accent-color to theme native checkboxes, radios, ranges, and progress — what it paints, what it skips, and when to custom-style instead.
- Auto-fit vs Auto-fillauto-fit collapses empty tracks; auto-fill keeps them. Use both with minmax for responsive card grids without media-query soup.
- BEM Naming MethodologyBlock, Element, Modifier naming for CSS — how it limits specificity wars, what to name, and when utility or CSS modules beat strict BEM.
- blend-mode Basicsmix-blend-mode vs background-blend-mode — how pixels combine, isolation, and the stacking/readability traps in product UI.
- box-sizing border-boxWhy border-box makes width include padding and border, the global reset pattern, and the layout bugs content-box still causes.