CSS architecture, utility frameworks, and animation performance Compiled for immediate developer deployment.
calendar_todaysummarizeWeek 7-2026
article
Launching Interop 2026 – Mozilla Hacks - the Web developer blog
TAG: RELEASE
Interop 2026 launches with 20 focus areas drawn from over 150 proposals, building on 2025's dramatic improvement from an overall score of 25 to 95. New CSS targets include scroll-driven animations, CSS container style queries, CSS attr() beyond pseudo-element content, CSS custom highlights via ::highlight(), and the responsive clip-path syntax CSS shape(). Cross-document View Transitions (with rel="expect" and blocking="render") and Scoped Custom Element Registries also made the cut. Reliability work continues on CSS scroll snap, CSS anchor positioning, CSS user-select, and CSS zoom — areas where spec ambiguities caused inconsistent browser behavior last year. Four investigation areas cover accessibility trees, mobile viewport testing, JPEG XL, and WebVTT.
READ_TIME: 7_MIN|BY: Jake Archibald Posted; Firefox; Uncategorized; Web Developers
Scroll indicators on tables with background colours using animation-timeline
TAG: TECHNIQUE
This short technique post solves a persistent CSS challenge: showing scroll shadow indicators on a horizontally overflowing table that has alternating row background colors — a case where the classic background-attachment: local approach and newer inset-shadow variants both fail because the table's own background covers the shadow. The solution wraps the table in a CSS Grid container (grid-template: "leftindicator content rightindicator" auto / 30px max-content 30px) and uses ::before/::after pseudo-elements with position: sticky and z-index: 10 as the indicators. Each pseudo-element gets a linear-gradient shadow and its opacity is driven by animation-timeline: scroll(nearest inline) via a simple @keyframes show-indicator that goes from opacity: 1 to opacity: 0, with ::before running the animation in reverse. The key reminder: always declare animation-timeline after the animation shorthand, or the shorthand resets it.
Temani Afif explains why height: 100% commonly fails — the parent needs an explicit height, and even then margin, padding, and box-sizing can cause overflow — and introduces height: stretch as a modern alternative. Unlike height: 100%, stretch works like align-self: stretch alignment and factors in margin automatically regardless of box-sizing. It also gives the element a definite height, enabling cascading stretch with a universal selector. For partial-fill cases like 80%, Afif pairs it with the calc-size() function: height: calc-size(stretch, .8*size), where the size keyword refers to the stretch value. Current limitation: height: stretch is Chrome-only at time of writing.
Mads Stoumann builds a fully interactive Pantone fan-deck component using only CSS — no JavaScript — by composing several cutting-edge features. The fan spread uses progress(100cqi, 300px, 1440px) to map container inline size to a continuous 0–1 value that drives rotation from -45° to +45°. Each card's rotation angle is computed with sibling-index() and sibling-count() — new CSS functions that give elements awareness of their position in the DOM. The <details name="deck"> exclusive-accordion pattern (only one open at a time) handles click-to-focus, while the new ::details-content pseudo-element with content-visibility: visible keeps card colors always rendered. Four:has()-based selector flags (--has-active, --is-before, --is-active, --is-after) drive a single rotation formula that collapses cards before and after the active one with a 0.25s linear transition. Browser support for progress() is currently Chrome and Safari only.
How to debug the @starting-style at-rule in Polypane | Polypane
TAG: GUIDE
The @starting-style at-rule — cross-browser since late 2023 and Chromium DevTools-supported only from version 143 (November 2025) — lets developers define an element's "from" state for CSS transitions when it is first added to the DOM, eliminating the need for two-stage JavaScript-driven reveals. Polypane has surfaced @starting-style in its Elements panel since version 20 (June 2024) because its devtools are designed for web developers rather than browser engineers: all styles across all states are always visible and editable. The article explains a key specificity quirk: because @starting-style has no specificity of its own, its inner selectors share specificity with the base rule, so the @starting-style block must appear last in source order to avoid being overwritten. Polypane also exposes a "force @starting-style" state toggle alongside :hover and :focus, enabling live debugging without re-adding elements.
CSS Animation Triggers: Playing animations on scroll without scrubbing. It's a match! | utilitybend
TAG: DEEP DIVE
Brecht De Ruyte explores CSS scroll-triggered animations — currently behind the experimental flag in Chrome Canary, expected in Chrome 146 — which let scroll position fire an animation without scrubbing through it frame-by-frame. Two new properties drive the feature: timeline-trigger (defined on a trigger element with a name, source like view(), and enter/exit ranges such as contain/cover) and animation-trigger (connecting an animation to that trigger with action pairs like play-forwards/play-backwards, play-once/none, or replay/none). The article demonstrates a Valentine's Day scrollytelling demo that combines scroll-driven backgrounds (animation-timeline: scroll(root)) with scroll-triggered text reveals, and shows how typed attr() syntax in Chrome can reduce dozens of trigger rules to a single CSS declaration. An @layer scrollTimeline pattern centralizes animation-range percentages for easier choreography.
Kevin Powell walks through replacing a JavaScript-based sticky nav on his personal Astro site with a pure CSS implementation using the new container-type: scroll-state. With this container type, child elements can query whether the container is stuck, snapped, or scrollable, enabling @container scroll-state(stuck: top) rules that apply nav styles — including a translate to slide the header in — without any JavaScript. He sets position: sticky with a negative top offset (e.g., top: -200px) so the nav hides off-screen and only slides back in once the user scrolls past that threshold. Powell also demos an animation-timeline: scroll() fallback using animation-range-start and animation-range-end in pixels, noting scroll-state had 71% global support (Chrome-only) vs. 78% for animation-timeline at recording time.
Launching Interop 2026 – Mozilla Hacks - the Web developer blog
Interop 2026 launches with 20 focus areas drawn from over 150 proposals, building on 2025's dramatic improvement from an overall score of 25 to 95. New CSS targets include scroll-driven animations, CSS container style queries, CSS attr() beyond pseudo-element content, CSS custom highlights via ::highlight(), and the responsive clip-path syntax CSS shape(). Cross-document View Transitions (with rel="expect" and blocking="render") and Scoped Custom Element Registries also made the cut. Reliability work continues on CSS scroll snap, CSS anchor positioning, CSS user-select, and CSS zoom — areas where spec ambiguities caused inconsistent browser behavior last year. Four investigation areas cover accessibility trees, mobile viewport testing, JPEG XL, and WebVTT.
Kevin Powell walks through replacing a JavaScript-based sticky nav on his personal Astro site with a pure CSS implementation using the new container-type: scroll-state. With this container type, child elements can query whether the container is stuck, snapped, or scrollable, enabling @container scroll-state(stuck: top) rules that apply nav styles — including a translate to slide the header in — without any JavaScript. He sets position: sticky with a negative top offset (e.g., top: -200px) so the nav hides off-screen and only slides back in once the user scrolls past that threshold. Powell also demos an animation-timeline: scroll() fallback using animation-range-start and animation-range-end in pixels, noting scroll-state had 71% global support (Chrome-only) vs. 78% for animation-timeline at recording time.
Scroll indicators on tables with background colours using animation-timeline
This short technique post solves a persistent CSS challenge: showing scroll shadow indicators on a horizontally overflowing table that has alternating row background colors — a case where the classic background-attachment: local approach and newer inset-shadow variants both fail because the table's own background covers the shadow. The solution wraps the table in a CSS Grid container (grid-template: "leftindicator content rightindicator" auto / 30px max-content 30px) and uses ::before/::after pseudo-elements with position: sticky and z-index: 10 as the indicators. Each pseudo-element gets a linear-gradient shadow and its opacity is driven by animation-timeline: scroll(nearest inline) via a simple @keyframes show-indicator that goes from opacity: 1 to opacity: 0, with ::before running the animation in reverse. The key reminder: always declare animation-timeline after the animation shorthand, or the shorthand resets it.
Temani Afif explains why height: 100% commonly fails — the parent needs an explicit height, and even then margin, padding, and box-sizing can cause overflow — and introduces height: stretch as a modern alternative. Unlike height: 100%, stretch works like align-self: stretch alignment and factors in margin automatically regardless of box-sizing. It also gives the element a definite height, enabling cascading stretch with a universal selector. For partial-fill cases like 80%, Afif pairs it with the calc-size() function: height: calc-size(stretch, .8*size), where the size keyword refers to the stretch value. Current limitation: height: stretch is Chrome-only at time of writing.
Mads Stoumann builds a fully interactive Pantone fan-deck component using only CSS — no JavaScript — by composing several cutting-edge features. The fan spread uses progress(100cqi, 300px, 1440px) to map container inline size to a continuous 0–1 value that drives rotation from -45° to +45°. Each card's rotation angle is computed with sibling-index() and sibling-count() — new CSS functions that give elements awareness of their position in the DOM. The <details name="deck"> exclusive-accordion pattern (only one open at a time) handles click-to-focus, while the new ::details-content pseudo-element with content-visibility: visible keeps card colors always rendered. Four:has()-based selector flags (--has-active, --is-before, --is-active, --is-after) drive a single rotation formula that collapses cards before and after the active one with a 0.25s linear transition. Browser support for progress() is currently Chrome and Safari only.
How to debug the @starting-style at-rule in Polypane | Polypane
The @starting-style at-rule — cross-browser since late 2023 and Chromium DevTools-supported only from version 143 (November 2025) — lets developers define an element's "from" state for CSS transitions when it is first added to the DOM, eliminating the need for two-stage JavaScript-driven reveals. Polypane has surfaced @starting-style in its Elements panel since version 20 (June 2024) because its devtools are designed for web developers rather than browser engineers: all styles across all states are always visible and editable. The article explains a key specificity quirk: because @starting-style has no specificity of its own, its inner selectors share specificity with the base rule, so the @starting-style block must appear last in source order to avoid being overwritten. Polypane also exposes a "force @starting-style" state toggle alongside :hover and :focus, enabling live debugging without re-adding elements.
CSS Animation Triggers: Playing animations on scroll without scrubbing. It's a match! | utilitybend
Brecht De Ruyte explores CSS scroll-triggered animations — currently behind the experimental flag in Chrome Canary, expected in Chrome 146 — which let scroll position fire an animation without scrubbing through it frame-by-frame. Two new properties drive the feature: timeline-trigger (defined on a trigger element with a name, source like view(), and enter/exit ranges such as contain/cover) and animation-trigger (connecting an animation to that trigger with action pairs like play-forwards/play-backwards, play-once/none, or replay/none). The article demonstrates a Valentine's Day scrollytelling demo that combines scroll-driven backgrounds (animation-timeline: scroll(root)) with scroll-triggered text reveals, and shows how typed attr() syntax in Chrome can reduce dozens of trigger rules to a single CSS declaration. An @layer scrollTimeline pattern centralizes animation-range percentages for easier choreography.
CSS had a landmark week centered on cross-browser coordination and scroll-driven innovation. The featured story, Interop 2026, launches with 20 focus areas — including scroll-driven animations, container style queries, and the new CSS shape() syntax — building on 2025's dramatic score leap from 25 to 95. That initiative sets the strategic backdrop for the week's technical tutorials, which show exactly what scroll-driven animations unlock in practice.
Three hands-on pieces push the animation-timeline frontier: a detailed exploration of the upcoming scroll-triggered animation API (Chrome 146), a technique for scroll-indicator shadows on banded tables using animation-timeline: scroll(nearest inline), and Kevin Powell's pure-CSS sticky-nav built with container-type: scroll-state. All three reach for the same goal — replacing JavaScript event listeners with declarative CSS — while acknowledging their current Chrome-leaning browser support.
Two shorter guides round out the week by tackling perennial CSS sizing pain points: height: stretch as a margin-aware alternative to height: 100%, and a JavaScript-free Pantone fan-deck built using the cutting-edge sibling-index() and progress() functions, demonstrating how much interactive UI CSS can now handle without a single event listener.
Key Takeaways
Interop 2026 officially targets scroll-driven animations and CSS shape() this year, meaning these features will reach reliable cross-browser support within the next 12 months.
animation-timeline: scroll() can replace JavaScript scroll listeners for opacity and transform effects today, but always declare it after the animation shorthand or the shorthand resets it.
height: stretch automatically factors in margins regardless of box-sizing, making it a cleaner alternative to height: 100% for filling parent containers — currently Chrome-only.