Safari Technology Preview 251 lands @supports at-rule(), random() with caching, corner-shape and object-view-box
Iris Calderón
You have wanted to feature-detect a top-level at-rule and had no clean way to do it. @supports gave you property/value pairs and, since @supports selector(), a selector-parses test. It stopped there. Any at-rule sniffed by proxy, through one of its nested properties, sometimes correctly and sometimes not.
Safari Technology Preview 251 fills that hole. It also ships a small pile of other CSS on top: two new functions, two new properties, a query addition, a shorthand rollup, and a new method on the Highlights API. One build, released 2026-08-26, covering WebKit changes 317935@main through 319386@main. Preview channel, one engine, no Baseline claim. The parser now knows a stack of names it did not last build.
@supports gets an at-rule test
Per the release, @supports at-rule(...) tests whether a specific CSS at-rule is supported. That is the piece missing from @supports for years. Detecting an at-rule used to mean sniffing a nested property inside it and hoping the browser did not parse-and-drop the container. Now the container itself is the target. Less indirection, less guessing.
random() gets a caching model
The random() story in this build has three pieces. The function itself gains property-scoped and property-index-scoped caching keywords, so you can control whether every element and every property call rolls its own value or shares one. random() also works inside a custom property in this build, so a fresh value can be baked into a variable and consumed downstream through the cascade. And a companion, random-item(), joins the ramp: pick from a list rather than a numeric range.
The keywords are the part to read closely. A random value that reshuffles on every layout pass is decorative noise. A random value locked per element and per property is authoring intent. That distinction is what the caching keywords name.
Two more CSS functions land: ident() and inherit()
ident() and inherit() both arrive as functions in this build. The release lists them as added; it does not show syntax bodies for either, so I am not going to type one. What it does commit to is that both parse. If you were planning to use them under a feature-detection block, you now have a preview channel to check against.
corner-shape and object-view-box, two new properties
corner-shape is the shape control that sits next to border-radius: the "what curve" question, separate from the "how much curve" question that border-radius already answers. object-view-box is a viewport into replaced content: you frame the visible portion of an <img> or <video> without cropping the source.
Both are the kind of primitive that used to require a wrapper element and a chain of overflow: hidden and transform: translate. That wrapper can start to go, once the pair lands cross-engine.
Container queries learn to speak in commas
Per the release, @container now takes a comma-separated list of conditions. Read that as OR at the container level: match when any of the listed conditions is true, without repeating the rule body.
This is the paper cut every design-system author has hit. Two container widths that want the same styles used to mean two identical @container blocks. Now they are one block with a comma between the conditions.
white-space-trim folds into the shorthand
white-space-trim had shipped in an earlier STP. In 251 it becomes part of the white-space shorthand. That is the small ergonomic change that turns a two-line declaration back into one, and it means the shorthand's reset behaviour now covers the trim value too. Set white-space: normal elsewhere in the cascade and you reset the trim along with the wrapping.
A Highlights API hit-test
HighlightRegistry.highlightsFromPoint() is a new method on the Highlights API in this build. Give it a point in the page, get back the custom highlights that render at that coordinate. If you have been styling text with ::highlight(name) and needed to answer which highlight sits under the cursor, this is the primitive you were otherwise writing yourself with Range gymnastics.
Where support stands, and how to gate
One preview channel, one engine. No Baseline claim on any item here, and I will not extrapolate one. What you can do today is exactly what STP is built for: wire up the syntax under a @supports block, keep the fallback path intact, confirm the parser accepts what you wrote. @supports at-rule() itself now makes those gates cleaner. You can test the container, not just its innards.
What to try on your next stylesheet
The two I would reach for first are @supports at-rule() and comma-separated @container conditions. Both are ergonomic wins that do not depend on new visuals landing. They clean up code that already works. random() with caching keywords is the one to prototype but not ship: fun, useful, and worth learning the caching model on now, so that when it lands across engines you already know which keyword you meant.
Source: WebKit Blog (webkit.org)