1.4 KiB
1.4 KiB
| title | source | updated | tags | |||||
|---|---|---|---|---|---|---|---|---|
| CSS animation + JS scrollLeft Conflict — Layout Thrashing | daily/2026-05-10.md | 2026-05-10 |
|
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
transformon every frame - JS sets
element.scrollLeft = xin 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