Right, let's talk about the bridge between CSS and JavaScript. For years, if you wanted to sync a React state machine with a CSS animation, you were basically playing a game of 'guess the timing'. You'd grab the elapsedTime from an event and hope it matched your CSS variables, or worse, you'd hard-code millisecond delays in JS that inevitably drifted out of sync with your stylesheets.
Chrome 151 has finally fixed this by adding a read-only animation property to both AnimationEvent and TransitionEvent. Instead of a string name and a timestamp, we now get the actual Web Animations API (WAAPI) object directly from the event. It’s a game-changer for design systems.
Why This Matters for Design Systems
In a robust design system, motion isn't just decoration; it's communication. We use it to signal that a sidebar has finished collapsing or that a modal is ready for interaction. Before Chrome 151, checking if an animation was actually 'finished' or 'running' meant reverse-engineering the animation-duration from the computed styles.
Now, the event gives you a live handle. You can inspect playState, currentTime, or even call pause() and reverse() on the animation that triggered the listener. It turns CSS animations into first-class citizens in your logic layer.
Wiring CSS into State Machines
I've found that the most reliable way to handle complex UI is to let CSS handle the GPU-accelerated movement while JS handles the state. With this new hook, we can drive a state machine with zero 'magic numbers'.
document.addEventListener('animationstart', (event) => {
// event.animation returns the CSSAnimation object
if (!event.animation) return;
const { animation } = event;
myStateMachine.send({
type: 'TRANSITION_START',
payload: {
name: animation.animationName,
duration: animation.effect.getTiming().duration
}
});
});
Notice how we're pulling the actual duration from the animation effect? If a designer changes the CSS from 200ms to 350ms, your JavaScript automatically knows. No more brittle timing hacks.
Debugging Jank and Pseudo-elements
We've all been there: an animation feels 'off', but you can't tell if it's dropping frames or just hasn't triggered. By combining the new animation object with the pseudoElement property, we can build much better debugging tools.
- Check
event.pseudoElementto see if the jank is coming from a::beforeor::afterdecoration. - Log
animation.playStateto ensure your 'end' events aren't being swallowed by DOM removals. - Use
animation.currentTimeto verify if an animation is starting from the beginning or resuming from a cached state.
Integration in React Components
If you're building a component library, you can wrap this in a hook. This allows your components to respond to CSS-driven motion without needing to know the specifics of the stylesheet.
function useMotionMonitor(ref, onComplete) {
useEffect(() => {
const node = ref.current;
if (!node) return;
const handleEnd = (e) => {
if (e.animation) {
console.log(`Finished: ${e.animation.animationName}`);
onComplete();
}
};
node.addEventListener('animationend', handleEnd);
return () => node.removeEventListener('animationend', handleEnd);
}, [ref, onComplete]);
}
A Few Gotchas to Watch For
While I'm genuinely excited about this, it's not a silver bullet. Firstly, event.animation can return null. Always include a null check before you try to access properties like playState. Secondly, remember that animationName is still just a string—the animation property is the live object. Don't confuse the two!
Wrapping Up
- Chrome 151 gives us direct access to the
CSSAnimationobject via event listeners. - Use this to eliminate hard-coded durations in your JavaScript and React logic.
- Leverage
playStateandcurrentTimefor more precise debugging of complex motion paths.
I'd encourage you to open up your current design system and see where you're using setTimeout to match a CSS transition. Replacing those with these new hooks will make your UI significantly more resilient.
If you want to go deeper and learn how to build real, production-ready CSS design systems step by step, check out my full course here: CSS Design Systems Course
The long version with support labels and runnable demos is in Modern CSS 2026 on Amazon Kindle.
Let's keep the conversation going! You can find me sharing more CSS tips on Twitter or connect with me for design system deep-dives on LinkedIn.