DEV Community

Leo
Leo

Posted on Originally published at news.html.to

@supports named-feature() lets you branch on behavior, not syntax

The test you can't write today

Say you want to branch a stylesheet on how an engine resolves anchor positioning around CSS transforms. Both browsers parse position-anchor. Both accept anchor(). The declarations look identical to @supports. What differs is behavior, and behavior is invisible to a parser check. Bramus opens on exactly this bind: @supports has only ever asked whether a string can be parsed, and there is a whole class of feature changes that never touch syntax.

Same story when two already-shipped properties suddenly work together. Neither is new. Neither triggers a fresh parse test. But the composed behavior is the news, and there has been no clean way to ask about it.

What @supports has been checking so far

The post lays out the three existing shapes:

  • A property and value together, like @supports (display: grid).
  • A selector, via selector().
  • An at-rule, via at-rule().

Each one asks the parser a yes/no. That covers the case where the news is a new property, a new value, a new selector, or a new at-rule. It stops being enough the moment the news is that an interop bug got fixed, or that two features have started to compose that did not before.

The named-feature() shape

named-feature() takes one predefined keyword:

@supports named-feature(single-axis-scroll-container) {
  /* only entered by engines that recognize this named behavior */
}
Enter fullscreen mode Exit fullscreen mode

No property. No value. No selector. Just an identifier a browser either recognizes and claims support for or does not. If the engine has never heard the name, the condition is false, the block is skipped, and whatever you write outside it stands as the fallback. Standard @supports semantics, new question.

Bramus flags two keywords currently on the table: anchor-position-follows-transforms and single-axis-scroll-container. Small list, on purpose. He notes the CSS Working Group only mints a keyword when a behavior is worth naming in the spec. That's the right calibration for a facility like this. If every quirk got a name, the surface would drown its own signal.

Why it earns its place

The alternative has always been the ugly stuff: user-agent sniffing, or a probe in JavaScript that measures a computed value on a hidden element and compares it against a baked-in table of "this engine does the thing". Both approaches go stale the day a browser ships a fix, and both push branching logic out of the stylesheet and into script.

named-feature() puts the answer where the branching already lives. Inside the cascade, at parse time, sitting next to the property it guards. That is the whole point.

It also gives a shape to something CSS has never quite had words for. There has always been a difference between "does the property exist" and "does it work the way the spec now says it should". Every interop story is really about the second question. Until now the language had no way to phrase it in-line.

What to watch

The interesting question isn't named-feature() itself. It's the keyword list. The primitive is only as sharp as the names the working group chooses to mint, and every future interop win — a rendering fix, a new composition between old features — is a candidate to become one. Read the post for the two names already in play. Then next time you find yourself in JS reading getComputedStyle to decide which CSS to send, check whether a keyword exists for what you're testing. If it does not, that's a proposal waiting to be filed.

Top comments (0)