v148 · CSS · @supports at-rule()

Feature Detector

Live at-rule detection for this browser. The CSS column uses @supports at-rule(…) in a stylesheet. The JS column uses CSS.supports('at-rule(@…)'). Compare the two.

runtime probe

Choose an at-rule and run the probe. Empty or malformed values are reported as invalid instead of silently failing.
At-rule
CSS @supports
JS CSS.supports()

How CSS detection works

/* Check if browser knows @layer */
@supports at-rule(@layer) {
  .layered-component { ... }
}

/* Check for @starting-style (enter animations) */
@supports at-rule(@starting-style) {
  dialog {
    opacity: 0;
    @starting-style { opacity: 0; }
    transition: opacity 0.3s;
  }
}

/* Check for @property (typed custom properties) */
@supports at-rule(@property) {
  @property --angle {
    syntax: "<angle>";
    inherits: false;
    initial-value: 0deg;
  }
  .spinner { animation: spin 1s infinite; }
}

Before @supports at-rule() — the old workaround

Before — JavaScript only

// CSS.supports() only checks property:value pairs
// It cannot check at-rule support
const hasLayer = CSS.supports('@layer');
// → always false (syntax not supported)

// Had to use browser detection or heuristics:
const isChrome105Plus = /Chrome\/(\d+)/.exec(
  navigator.userAgent
)?.[1] >= 105;
if (isChrome105Plus) {
  document.body.classList.add('has-layer');
}
// Brittle. User-agent sniffing = bad.

Chrome 148 — CSS + JS

/* Pure CSS: */
@supports at-rule(@layer) {
  /* only if @layer is understood */
  .nav { layer: nav; }
}

/* JavaScript: */
CSS.supports('at-rule(@layer)')
// → true in Chrome 99+, false older

CSS.supports('at-rule(@starting-style)')
// → true in Chrome 117+

CSS.supports('at-rule(@scope)')
// → true in Chrome 118+

references

implementation reference

Need the exact API surface, compatibility boundaries, errors, lifecycle, and source links? Read the matching gendn reference ↗