WebCraft

@container style()

A component that reads its own token

Live demo

deployed
needs review
archived

Caveat and fallback

CaveatA style query is answered by the element's nearest ancestor container, and every element is one, so the custom property has to live on an ancestor of whatever you are styling and never on that element itself. Only custom properties can be asked about today, so style(display: flex) matches nothing, and an unregistered property is compared token by token, which makes 1 and 1.0 two different answers.

FallbackWith no support none of the blocks match and every badge keeps the base styling, so write that base as the neutral state rather than as one of the variants. For two variants a plain class is shorter and works everywhere; style queries start paying once a token set several levels up has to reach a component nobody wants to pass a class to.

Source code

HTML + CSS
<div data-tone="warn"><span>review</span></div>

[data-tone="warn"] { --tone: warn; }

/* the child asks its ancestor, not itself */
@container style(--tone: warn) {
  span { color: var(--margin); }
}

Published

Questions

<details name>

What is a CSS style query?

A container query that asks about a custom property instead of a size: @container style(--tone: warn). It lets a component pick up a token set by an ancestor without anyone passing a class down to it.

Why is my @container style() query not matching?

Usually the property is set on the same element the rule is trying to style. A query is answered by the nearest ancestor container, and an element is never its own container, so the token has to sit one level up. The other common cause is comparing an unregistered property, which is matched token by token, so 1 and 1.0 do not agree.

Can I query a normal property such as display?

Not yet. Style queries are limited to custom properties, so style(display: flex) matches nothing at all. Copy whatever you need into a custom property alongside the real declaration and query that.