DEV Community

Leo
Leo

Posted on • Originally published at news.html.to

Safari Technology Preview 248 gives progress() a no-clamp option and forwards missing components across analogous color spaces

Progress ratios are how you turn a size into a signal. You measure some quantity, a scroll offset or a container width, and you want the value from zero to one that says "how far along". CSS's progress() function does exactly that. It takes a value and two bounds and hands you back a normalised ratio. Until now in this engine, it clamped the result. Below zero became zero. Above one became one.

Safari Technology Preview 248, dated 2026-07-22 and covering WebKit changes 315567@main through 316817@main, adds a no-clamp option to progress(). Per the release, that is the entry: progress() gains a keyword that opts out of the clamp. What that reads as, from the name alone, is that the ratio is allowed to run negative or past one instead of being pinned to the [0,1] range. Which is exactly what you want when a stylesheet is mapping something that crosses the bounds of its input range. A scroll-linked value that overshoots. A container query reading a size beyond its declared endpoints. Clamp when you need a saturated signal. Skip the clamp when the signal itself is what you're mapping. The release does not spell out the exact syntax slot for the keyword, so read the linked spec text before you write more than a scratch rule.

Missing color components, forwarded across analogous spaces

The other CSS headline is subtler. When two colors are interpolated in an intermediate space, individual components can be missing. An OKLCH color with no hue channel. A Lab color whose a and b axes are undefined. The interpolation rules already have language for what happens when one side is missing a component the other one carries. What STP 248 adds is forwarding: per the release, when the interpolation happens between analogous color spaces, a missing component on one side is forwarded from the other side rather than being invented or dropped.

The reason this matters is what it does to gradients and to color-mix() on the wrong day. Any time you interpolate between two colors whose spaces line up along the same coordinate axes, a missing hue or chroma on one side used to give you a subtly wrong midpoint. The engine now carries the other side's value through. Smoother interpolants, no invented data.

Two accessibility fixes worth naming

VoiceOver on Safari can now navigate into content revealed by disclosure widgets that use hidden="until-found". That attribute is the one you set on collapsed content so the browser can reveal it during in-page find. Before this fix, VoiceOver treated the revealed region as still hidden and skipped past it. Now the assistive-tech cursor follows the reveal.

The other one is a stale-state repair. When an element referenced by aria-labelledby changed its aria-label at runtime, the label consumed by the referring element could go stale. STP 248 resolves that. If you build components that swap an accessible name in place, this is one less way for the wrong name to leak.

The quieter CSS fixes

Three more lines from the release earn a mention.

Scroll snap re-snap now prefers the :target snap area. If the URL fragment points at a snap child, that child wins the re-snap decision, which is the intuitive resolution.

var() only resolves its fallback when the first argument is the guaranteed-invalid value. That is the spec behaviour, and the engine now matches it. A custom property set to something present but odd no longer swaps in the fallback anyway.

Serialization of CSSViewTransitionRule was incorrect and is now right. Round-tripping the rule via .cssText should hand you back what you put in.

Where this leaves you

STP 248 is a single-engine preview. The notes make no Baseline claim, and neither do I. The two CSS additions, progress() with no-clamp and forwarded missing components across analogous color spaces, are the sort you can wire into a scratch page today and gate behind @supports if you want to try them in a real one. The accessibility fixes need no gating. They are behaviour repairs. Available for anyone testing in this preview build.

What I'd try next: put a scroll-linked value through progress() with the new keyword and watch what it does at the ends of its range. It is the smallest change in the release, and the one likeliest to change how you write a scroll-driven rule.

Top comments (0)