Skip to content

How to build a CSS @supports query and read the exported block

The builder turns a property and a value into one CSS feature test and wraps it in an @supports block. A second test can join with and or or, the whole query can be negated, and the verdict is answered by CSS.supports() in the browser that is running the page - this browser only, not your visitors.

Five presets cover the tests that come up most often: display: grid, container-type: inline-size, color: oklch(60% 0.2 140), backdrop-filter: blur(8px) and the selector test selector(:has(*)). Picking one fills the property and value fields and clears the combiner; every edit afterwards switches the select to Custom.

  1. Pick a preset or type a property and its value. The query line, the badge and the exported block follow the fields as you type; there is no run button.
  2. Set Combine with to "and" or "or", then fill the second property and value. A row only joins the query once both halves are filled: a half-filled row is skipped instead of being exported as (: ).
  3. Tick Negate query to wrap the condition in not. A single test prints not (display: grid); a combination prints not ((display: grid) and (gap: 1rem)).
  4. Enter the CSS that should apply when the test passes. Every line of the rules field is indented by two spaces inside the exported @supports block.
  5. Read the badge, then press Copy CSS. Reset restores the .component rules and the grid preset.

Presets, the value field and what the verdict covers

Tests that stand on their own

selector(), font-tech() and font-format() are complete tests by themselves: type selector(:has(*)) or font-tech(color-COLRv1) in the property field and the value field does not take part. A property and value pair is only wrapped as (property: value) once both halves are filled.

An empty property or an empty value leaves the query empty: the badge reads "No condition yet" and the export stays empty instead of shipping a malformed (: ) block, which is what the page produced before this pass. Negation is honest in the same way - @supports not (property: value) matches when the declaration is not supported, unknown properties included, so a negated unknown property reports as supported.

What the verdict covers, and what it does not

CSS.supports() runs in the page, so the badge describes the browser you are using and nothing else. In the probe run Chrome 153 answered true for (display: grid), (container-type: inline-size), (color: oklch(60% 0.2 140)), (backdrop-filter: blur(8px)) and selector(:has(*)); an older browser would show different verdicts on the same page.

A green badge means the condition parses and is supported here; it is not a compatibility table for your audience. Keep a plain declaration before the @supports block and the browsers that fail the test fall back to it.

The export, and where the work happens

The exported block is @supports <condition> { <rules> }: the condition is printed exactly as tested, and each line of the rules field is indented by two spaces. The rules text itself is copied as typed, comments and fallback declarations included, and Copy CSS puts the code panel on the clipboard character for character.

Everything runs inside the page. Typing, the presets, the combiner, the negation, Copy CSS and Reset sent zero network requests in the probe (en, fr and ja), and the tool keeps working offline; the only third-party request on the page comes from the shared analytics tag.

Recent tools: