Techniques Worth Stealing

Preethi Sam showed how to build background image refraction effects in CSS. They animate, require little CSS, use no JavaScript, and don't require duplicating the image. Brecht De Ruyte, meanwhile, covered customizable components built from container style queries paired with advanced attr(), backed by interactive demos.

Dan Holloran's walkthrough of the scroll-state() queries — scrollable, scrolled, snapped and stuck — is a short read, which suits a feature this straightforward. The snippet below gives a taste without context:

@container scroll-state(stuck: top) {
  /* ... */
}

For animating grid layouts, Bramus anchors content to its corresponding cell so that when the grid reflows, the content — not the cell — animates along with it. The approach currently breaks in Firefox, apparently because of a bug.

Declan Chidlow collected some of the craziest CSS ever written, much of it from Internet Explorer. Remember this one?

-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(opacity=50)";

Container Queries, @custom-media and Overlap Detection

Victor Ayomipo argues that container query adoption has been poor despite years atop CSS wishlists because we're using them wrong, and he sets out to correct that. Cory LaViska follows the same thread with a demonstration of @custom-media used alongside container style queries as a fallback.

Ahmad Shadeed's piece on detecting overlapping elements in CSS leans on anchor positioning, scroll-driven animations and container style queries — another sign the queries may finally be gaining traction.

Selector, Border and Scroller Tricks

Animating the background color of ::selection was long assumed to be forbidden. Leon Arnott's solution rests on making the color a variable inherited from the parent element and registered with @property so it becomes animatable:

  1. Register --bg-color using @property.
  2. Animate --bg-color's value using @keyframes.
  3. Declare --bg-color: inherit on ::selection.

Then reference var(--bg-color) on ::selection, or on another similarly restrictive element.

Temani Afif's custom borders demo works by declaring a transparent border, giving it a shape with border-shape, then adding a background together with background-clip: border-area so the background appears only inside the border. It currently requires Chrome.

Polypane documented how easily the root scroller can be disabled by accident, what that costs, and what to do instead; the same article serves as a solid explainer of how :root/html actually behaves. On the input side, Andy Bell points out that touch-action: manipulation disables double-tap-to-zoom. It isn't new, but few developers apply it — a candidate for the CSS reset.

HTML Proposals and Features

Chris Coyier rounded up a batch of new HTML features, most of which are unlikely to be familiar. Patrick Brosset walked through a proposal for a previewsrc HTML attribute that would let authors supply preview images — a blurry placeholder, for instance — for images that haven't loaded yet, using only HTML. A CSS-first alternative would be something like :loaded/:not(:loaded) for styling and transitioning unloaded images without generating extra image files.

Chris Coyier also demonstrated randomly animating an element along the edge of another element with random(). The demo includes a dog.

Release Notes

Chrome and Firefox now ship every two weeks, and their inaugural releases were substantial rather than smaller as one might have assumed. Safari 27, along with iOS, iPadOS and macOS 27, shipped several of the same features as Firefox in the same window, making them Baseline together.

  • Firefox 155: alpha(), progress() and advanced attr(), all now Baseline.
  • Chrome 153: scroll-axis-lock, <camera> and <microphone> (none supported in Safari or Firefox).
  • Safari 27: revert-rule, alpha(), progress(), light-dark() image values and sizes=auto, now Baseline; 3+ color values for color-mix() and ariaNotify (no Chrome support); stretch, transform-aware anchor positioning and customizable <select> (no Firefox support); :heading (no Chrome or Firefox support).
  • Chrome 154: text-decoration-inset (no Safari support); frame-sizing and scroll-marker-group modes (no Safari or Firefox support).
  • Firefox 157: at-rule() and overscroll-behavior: chain (neither supported in Safari).

Text styling and interaction refinements have shipped alongside the layout and query features: an HTML attribute for choosing preview images, ways to draw custom borders, animated selection colors, randomized motion, and a pair of viewport pitfalls to watch for.

New HTML features

The previewsrc attribute joins the HTML attribute set covered in this roundup. It is read alongside src rather than replacing it, giving markup a place to declare the asset used for a preview.

Custom borders demo

The border property accepts element(), so a rendered element can be used as a border image. The demo pairs that with border-image-repeat: round to tile the rendered element cleanly around the edge instead of stretching it.

How to animate the background color of ::selection

Selection highlighting can now be transitioned with transition: background-color on ::selection. Under the hood this is driven by the ::selection pseudo-element and supports custom properties, so the highlight color can be themed through a variable rather than hard-coded in the rule.

How to randomly animate an element along another element

Keyframe animations normally travel a fixed path, but the shape() function changes that: a keyframe can move an element along the perimeter of another element's shape, and by inserting a random function into the path, the movement varies on each run.

Two scrolling pitfalls

Both problems below share one root cause: an overflow wheel-scroller modifier on a fixed-positioned element can change which box the page treats as its root scroller.

  • Disabling the root scroller accidentally. The root scroller stops responding to window.scrollTo() and similar imperative scrolling APIs. Keeping position: fixed out of the ancestor chain of the scroller avoids it.
  • Breaking double-tap-to-zoom. Disabling double-tap-to-zoom is usually done with touch-action: manipulation on the specific element or touch-action: pan-x pan-y as a global default. Doing it globally breaks pinch-zoom for users who rely on it, and attaching touch-action: manipulation to everything turns it off across the document.

For the global case, the @media (pointer: coarse) query is the narrower alternative: scope the touch behavior to touch input only, leaving mouse and trackpad environments out of it.