Scroll-driven animation gắn tiến độ animation vào vị trí cuộn thay vì vào thời gian, và chạy ngoài main thread.
Hai loại timeline:
css
/* 1. scroll() — theo tiến độ cuộn của cả vùng cuộn */
@keyframes grow { from { transform: scaleX(0); } to { transform: scaleX(1); } }
.progress-bar {
transform-origin: left;
animation: grow linear;
animation-timeline: scroll(); /* mặc định: vùng cuộn gần nhất, trục dọc */
}
/* 2. view() — theo vị trí của chính element trong viewport */
@keyframes fade-up { from { opacity: 0; translate: 0 20px; } to { opacity: 1; translate: 0 0; } }
.card {
animation: fade-up linear both;
animation-timeline: view();
animation-range: entry 0% entry 60%; /* chạy trong lúc element đang đi vào */
}So với cách cũ: scroll listener + IntersectionObserver + tính toán trong JS — chạy trên main thread, dễ giật khi trang đang bận.
Hỗ trợ: Chrome 115+, Firefox 128+, Safari chưa có (tính tới 2026). Vì vậy luôn cần dự phòng.
css
@supports (animation-timeline: view()) { /* chỉ bật hiệu ứng khi hỗ trợ */ }Lưu ý: quên @media (prefers-reduced-motion: reduce).
Hiệu ứng gắn với cuộn dễ gây khó chịu cho người nhạy cảm với chuyển động hơn hẳn animation thường, vì nó xảy ra liên tục theo mỗi thao tác cuộn.