The Chrome 150 release notes crossed my radar while it was still in beta, flagged as an easing update for motion people. So I read the whole changelog expecting new timing functions. There aren't any. What's actually in there is stranger and, honestly, more useful, as long as you know which version shipped what.
Quick housekeeping first: Chrome 150 went beta on June 2, 2026 and hit stable at the end of that month. It's old news by the time you read this. The features are not.
TL;DR: Chrome 150's only animation change is animatable
zoom, which interpolates as a number and reflows layout as it grows. The media state pseudo-classes widely credited to it ship in Chrome 152.linear()easing dates to Chrome 113 in May 2023. Scroll-driven animations run in Chrome 115+ and Safari 26 and stay behind a flag in stable Firefox. Updated September 2026: scroll-triggered animations, a different feature, shipped in Chrome 146, not the 145 that Chrome's own blog still claims.
The One Real Animation Change: Animatable Zoom
The zoom property has been around since the Internet Explorer days, but animating it used to snap between values. As of Chrome 150 it interpolates as a number, per the official Chrome 150 release notes, which means this now tweens smoothly:
.card {
zoom: 1;
transition: zoom 300ms ease-out;
}
.card:hover,
.card:focus-visible {
zoom: 1.06;
}
Why would you reach for this instead of transform: scale()? Layout. Scale is paint-only, so neighbors never move. Zoom resizes the element for real and the page reflows around it. An expanding card that pushes its grid siblings aside used to need JavaScript or grid-row tricks. Now it's one property.
My honest take: animatable zoom is a trap for most decorative motion. Reflow on every frame is main-thread work, and I'd still ban it from anything that runs during scroll. Use it for deliberate, single-shot layout moments, the kind of intentional micro-interaction that earns its frame budget. Nothing else.
Reading about a reflow isn't the same as watching one happen. So here's the lab I built while fact-checking this post: it runs all three features below in whatever browser you have open right now. The four badges up top are live feature tests, not a compatibility table somebody updated last year, and the zoom badge specifically drives a paused animation to its midpoint and reads the value back, which is the only honest way to tell interpolation from a snap.
Play the zoom demo, then switch the toggle to transform: scale() and play it again. The readout under the cards measures how far the right-hand sibling actually moved. Same target size, one number is tens of pixels and the other is zero.
Did the Media State Pseudo-Classes Ship in Chrome 150?
No. They ship in Chrome 152, and the mix-up is the sharpest example in this whole release of why you read the notes instead of the headline. The Chrome 150 beta post described the media element pseudo-classes :playing, :paused, :seeking, :buffering, :stalled, :muted, and :volume-locked, which match audio and video elements by playback state. They are not in the stable release notes linked above. They turn up in the Chrome 152 beta writeup instead, two versions downstream.
I got this wrong myself while drafting, because the beta post is what search surfaces first. So did a fair chunk of the coverage. Features slip between beta and stable, and a beta announcement is not a shipping record.
Worth the wait, though. Styling custom player chrome by playback state, with no JavaScript listening for play and pause events, kills an entire category of desync bug: the button that says paused while the video plays. They are also a focus area in Interop 2026, the annual cross-browser project where the engine vendors publish a shared list of compatibility gaps and commit to closing them that year. So the other engines are on the hook.
Is linear() Easing New in Chrome 150?
No, and this is where version numbers matter most. The linear() function shipped in Chrome 113 back in May 2023, with Firefox 112 slightly ahead of it and Safari catching up in 17.2 that December. What changed by 2026 is confidence: it's Baseline, the web platform's label for a feature that works across every current major engine, and I've stopped writing fallbacks for it.
The name is terrible. What linear() really gives you is a piecewise curve built from points, which means bounce and spring shapes that cubic-bezier() physically can't describe. A bezier gets one hump. A spring needs several.
.badge {
animation: pop-in 700ms forwards;
animation-timing-function: linear(
0, 0.402 7.4%, 0.867 14.5%, 1.25 21.5%,
1.121 29%, 0.964 36.5%, 1.011 44%,
0.997 51.5%, 1
);
}
@keyframes pop-in {
from { transform: scale(0.6); }
to { transform: scale(1); }
}
Each pair is an output value and a progress percentage. The curve overshoots to 1.25, dips under, and settles: a spring, in pure CSS, running on the compositor. Chrome's own linear() documentation links a generator that converts real spring physics into these point lists, so nobody types them by hand. When I tested a spring like this against an equivalent JS-driven one, the CSS version survived a busy main thread without a stutter. The JS one didn't.
Can You Ship Scroll-Driven Animations Yet?
Yes, as an enhancement, in three of the four engines. Same rule as linear(), different feature: animation-timeline is a Chrome 115 story from July 2023, not a Chrome 150 one. The state in late 2026 looks like this:
- Chrome and Edge: shipped since 115, stable for three years
- Safari: shipped in Safari 26, September 2025
- Firefox: still behind a flag in stable builds as I write this
- Interop 2026: scroll-driven animations are an official focus area, alongside media pseudo-classes and the
zoomproperty itself
Landing on that Interop list is the strongest public signal you get that a holdout engine intends to catch up. That Firefox gap is the whole production question. Is it a blocker? Not if you treat scroll-driven motion as enhancement:
@supports (animation-timeline: view()) {
.reveal {
animation: fade-up linear both;
animation-timeline: view();
animation-range: entry 0% entry 60%;
}
}
@keyframes fade-up {
from { opacity: 0; transform: translateY(24px); }
to { opacity: 1; transform: none; }
}
Firefox users see the content sitting there, fully readable. Everyone else gets the reveal. The Mozilla Developer Network (MDN) scroll-driven animations guide covers the scroll() variant for progress bars and the named timeline syntax for when the scroller and the animated element live in different subtrees. We went deeper on where these timelines beat ScrollTrigger from GSAP (the GreenSock Animation Platform), and where they don't, in our CSS vs GSAP comparison, and the short version still holds: there is no pinning in the spec, so pin-heavy designs stay in JavaScript, where Framer Motion and ScrollTrigger still own the problem.
Update, September 2026: Scroll Triggers Shipped in Chrome 146
Here's the correction this post earned. Checking what landed since June, I went looking for the feature people keep expecting from each new Chrome, and found it had been sitting in stable for six months already.
Scroll-triggered animations. Not scroll-driven ones. One word apart, and a completely different job.
animation-timeline maps animation progress onto scroll position, so scrolling scrubs the animation like a video playhead. Drag back up, it plays backwards. animation-trigger does something else entirely: it watches for a scroll position and fires an ordinary time-based animation when you cross it. Play, pause, reset. Once it starts, it runs on its own clock and ignores how fast you scroll.
That gap is bigger than the naming suggests. Nearly every reveal-on-scroll effect I've built since 2023 wanted the second behavior and got assembled out of IntersectionObserver instead, because CSS only offered the first.
The shipped syntax uses three properties, documented in the Chrome 146 release notes:
.gallery {
trigger-scope: --reveal;
}
.gallery-track {
timeline-trigger: --reveal view() entry 100% exit 0%;
}
.gallery-card {
animation: fade-up 500ms both;
animation-trigger: --reveal play-forwards play-backwards;
}
timeline-trigger names a trigger and declares the range that arms it. animation-trigger points at that name and says what to do on the way in and on the way out. trigger-scope keeps the name from leaking, because trigger names are global by default, the same way anchor-name is. Leave that third property off a page with two galleries and they will happily drive each other.
Now the part that made me rewrite this section twice. Chrome's own feature blog says scroll-triggered animations are "landing in Chrome 145". They aren't in the Chrome 145 release notes at all. The original Intent to Ship thread said 144. The feature actually reached stable in 146, on March 10, 2026. That's three published version numbers for one feature, and only one of them is right.
So this post's own rule survived contact with its subject: the beta post was wrong about 150, and the feature blog is still wrong about 145. Where does that leave you? Stable release notes, or a live @supports test. Nothing in between is trustworthy.
One behavior change matters if you adopt this. As of Chrome 151, the play, play-forwards and play-backwards trigger actions no longer auto-rewind an animation that already ran to completion. Re-entering the range used to restart it. It doesn't anymore. If a reveal of yours fired once and then went silent after a browser update, that's the change, and reset is the action you're missing.
Two dates for context while you plan: Chrome 152 has been stable since August 25, 2026, so the :playing floor this post told you to wait for is already behind you. Chrome 153 follows on September 8.
Should you ship scroll-triggered CSS now? Not on its own. It's Chrome-only as I write this, with nothing in Safari or Firefox, so it belongs on top of content that reads fine without it. Here's where I expect disagreement: in a Chrome-heavy internal tool I'd already pick animation-trigger over an IntersectionObserver, because deleting the observer deletes a whole category of the main-thread stalls that make scroll animation feel cheap. On a public marketing site, wait for a second engine.
The Motion Designer's Chrome 150 Watchlist
Some Chrome 150 additions aren't animation properties at all, yet each one deletes a workaround motion work has leaned on for years. Which lands in your CSS first? For me it was the gradient border:
text-fitscales the font size of a text node to fill the width of its containing box, which is kinetic typography plumbing. Pair it with the reveal patterns from our motion design guide and headline lockups stop needing resize observers. It does not replace a modular type scale; it fits one line of type to one box.flex-wrap: balanceevens out flex lines the waytext-wrap: balanceevens out headlines. Fewer orphaned cards mid-animation.background-clip: border-areagives you gradient borders natively, and animating a gradient border's hue is now a two-line hover effect. The best-known animated gradient border in the wild is Apple's, and the Apple Intelligence UI guide breaks down its exact colors, and the conic-gradient and @property recipe is precisely the workaround this property retires.
What actually surprised me across this whole release cycle? The pattern. Chrome's animation story in 2026 isn't splashy launches; it's unglamorous plumbing like animatable zoom plus Interop pressure dragging older features toward Baseline. That's better for working designers than another headline API. New syntax you can't ship is trivia. Old syntax that finally works in three engines is a tool.
So the practical read on Chrome 150: adopt linear() today without guilt, wrap scroll timelines in @supports and ship those too, treat animatable zoom as a scalpel, and hold off on :playing until 152 is your floor. Version numbers, not release hype, tell you which is which. And when the two disagree, the stable release notes win.