v137 · css

Progressive Enhancement

if(supports(…)) within a CSS declaration lets you apply a new CSS feature when available and fall back gracefully when not — all inline, without a separate @supports rule wrapping an entire block. Each property gets its own fallback right where it's declared.

Feature detection: checking…
Note: CSS if() is not supported in this browser. The progressive enhancement patterns will not apply. Use Chrome 137+.

corner-shape: squircle fallback

border-radius: if(supports(corner-shape: squircle): 30%; else: 50%) — same rounded card, just a squircle when the browser supports it.

corner-shape
progressive
same markup
both browsers
no @supports
block needed
In Chrome 139+: squircle corners. In older browsers: circular (50% border-radius).

text-box trim fallback

text-box: if(supports(text-box: trim-both): trim-both; else: normal) — tight leading when supported, standard line-height elsewhere.

with text-box: trim-both (when supported)

Headline Text

Body text immediately after the heading with no extra leading space above or below.

what you see depends on your browser

Tight Spacing

Chrome 137+ trims the invisible space above the cap-height and below the baseline — one inline if() does it.

container query layout fallback

display: if(supports(container-type: inline-size): grid; else: block) — icon+text two-column layout when container queries are available.

🚀
Launch ready
In Chrome with container-type support: icon on the left, text on the right in a grid layout. In older browsers: icon stacked above text in block flow.

before vs after

patternwithout if(supports())with if(supports())
corner-shape @supports { .card { corner-shape:… } } border-radius: if(supports(…): 30%; else: 50%)
text-box @supports rule wrapping h1, p declarations text-box: if(supports(…): trim-both; else: normal)
container-type layout @supports (container-type:…) { display: grid } display: if(supports(…): grid; else: block)
cascade location fallback and enhancement are in separate blocks fallback and enhancement are in the same declaration
specificity @supports adds no specificity but changes cascade if() resolves at computed-value time, no specificity effect
/* Old pattern: @supports blocks all properties together */
.card {
  border-radius: 50%;
}
@supports (corner-shape: squircle) {
  .card {
    border-radius: 30%;
    corner-shape: squircle;
  }
}

/* New pattern: each property carries its own fallback */
.card {
  border-radius: if(supports(corner-shape: squircle): 30%; else: 50%);
  corner-shape:  if(supports(corner-shape: squircle): squircle);
  /* fallback: property simply unset or uses initial value */
}

see also