When CSS @supports Is Useful

Browsers already ignore declarations they do not understand. That means a new CSS value often needs no feature query at all:

.button {
  background: #3366ff;
  background: oklch(62% 0.18 250);
}

An older browser keeps the hex colour. A newer one replaces it with oklch(). I use @supports when the fallback needs more than this natural cascade.

Put the working baseline first

.card {
  display: block;
}

@supports (display: grid) {
  .card {
    display: grid;
    grid-template-columns: 1fr 2fr;
  }
}

The condition tests a property-value pair. It tells you whether the browser parses that declaration, not whether its implementation is bug-free or appropriate for your particular layout.

Newer optional behaviour is a good fit:

@supports (field-sizing: content) {
  textarea {
    field-sizing: content;
  }
}

The textarea remains usable without the enhancement.

Selectors can be queried too

@supports selector(:has(*)) {
  .field:has(input:focus) {
    outline: 2px solid currentColor;
  }
}

Use and, or, and not when a fallback genuinely depends on a combination:

@supports (display: grid) and (gap: 1rem) {
  .layout {
    display: grid;
    gap: 1rem;
  }
}
@supports not (display: grid) {
  .layout {
    display: flex;
  }
}

I usually keep the fallback outside the not block. It is easier to find, and it remains the default when a browser does not understand feature queries themselves.

Do not put the page behind a test

@supports (new-feature: value) {
  body {
    display: block;
  }
}

If essential content exists only inside a support condition, progressive enhancement has gone missing. Start with a usable page and query the polish.

For example, keyword-size interpolation can enhance an otherwise ordinary panel:

.panel {
  height: auto;
}

@supports (interpolate-size: allow-keywords) {
  .panel {
    interpolate-size: allow-keywords;
    transition: height 250ms;
  }
}

My check is simple: if ignoring one declaration leaves an acceptable result, let the cascade handle it. If the browser needs a different group of rules, @supports makes that decision explicit.