---
title: "CSS animation + JS scrollLeft Conflict — Layout Thrashing"
source: daily/2026-05-10.md
updated: 2026-05-10
tags: [css, animation, javascript, scroll, performance]
---

# CSS `animation` + JS `scrollLeft` Conflict — Layout Thrashing

## Rule

Never write to `scrollLeft` (or `scrollTop`) on an element that has an active CSS `animation` targeting `transform` or `left`. The two systems fight over the same rendered position every frame.

## What Happens

- CSS animation runs in the compositor thread, updating `transform` on every frame
- JS sets `element.scrollLeft = x` in the main thread
- Browser must sync both on each paint → triggers layout thrashing
- Result: animation "freezes" for a frame, then jumps to catch up; or stutters continuously

This was observed in a GallerySlider component: `animation-play-state` toggled on hover while `scrollLeft` was set on arrow-button click. The combination caused a 1-second freeze at animation start.

## Fix

Pick **one** scroll mechanism and remove the other entirely:

| Goal | Approach |
|------|----------|
| Auto-scroll with buttons | Pure JS: `requestAnimationFrame` loop, no CSS animation |
| Pure marquee | CSS `@keyframes translateX`, no `scrollLeft` at all |
| Gallery (snap) | CSS `scroll-snap` + `scrollTo({ behavior: 'smooth' })`, no `@keyframes` |

## Related

- [[wiki/concepts/css-marquee-animation-gpu-pattern]] — the pure-CSS marquee pattern that avoids this conflict
