"매 compositor-only properties + GPU thread + 매 main thread 의 minimal involvement". 매 60fps (16.67ms budget) / 120fps (8.33ms) 에서 jank-free 한 animation 의 매 핵심: transform/opacity/filter 만 animate, layout/paint trigger 회피, 매 2026 의 View Transitions API + scroll-driven animations 활용.
Scroll-driven animations (parallax, progress bar) — 매 main thread 떠남.
View Transitions API — cross-document morph (MPA, SPA route).
💻 패턴
Compositor-only animation (CSS)
.card{transition:transform200mscubic-bezier(0.2,0.8,0.2,1),opacity200msease;will-change:transform;/* hint — remove after animation */}.card:hover{transform:translateY(-4px)scale(1.02);}
FLIP technique (animate layout change without layout-trigger)
requestAnimationFrame loop with frame budget guard
letlast=0;functiontick(now: number){constdt=now-last;last=now;conststart=performance.now();updatePhysics(dt);if(performance.now()-start>8){// Defer non-critical to next frame or scheduler.postTask
scheduler.postTask(refreshLowPriorityUI,{priority:'background'});}render();requestAnimationFrame(tick);}requestAnimationFrame(tick);
Web Animations API — JS-controlled but GPU-eligible
Pointer interaction with Pointer Events + passive listener
el.addEventListener('pointermove',(e)=>{// No preventDefault — listener can be passive (bypass main thread blocking)
constx=e.clientX,y=e.clientY;el.style.transform=`translate3d(${x}px, ${y}px, 0)`;},{passive: true});
기본값: 매 transform + opacity only. 매 width/height/top/left animate 의 X (rare exception 만). 매 will-change 는 short-lived hint (animate 시작 직전 add, 끝나면 remove).
언제: easing curve 의 candidate generation, FLIP boilerplate, View Transition CSS 의 scaffold.
언제 X: 매 perf 측정 — DevTools Performance panel + WebPageTest 만 truth. Jank cause 의 매 nuanced.
❌ 안티패턴
width/height/top/left animation: 매 layout-trigger, 매 jank.
box-shadow animation: paint-heavy, blur-radius 변화 의 expensive.
will-change everywhere: 매 GPU memory 폭증, 매 reverse effect.
JS rAF for what CSS can do: scroll-driven CSS 가 매 main thread free.
Synchronous layout reads in animation loop: getBoundingClientRect during rAF without batching → forced reflow.
🧪 검증 / 중복
Verified (web.dev/animations 2026, Chrome DevTools Performance docs, View Transitions Level 2 spec, Una Kravets / Bramus Van Damme writings).