Animasi yang digerakkan gulir — bilah kemajuan baca yang terisi di atas halaman, kartu yang memudar masuk saat melintasi layar — selama ini menuntut JavaScript: mendengarkan event scroll, membaca posisi, lalu menghitung nilai animasi pada setiap piksel gulir. Pola itu berat dan rawan: event scroll tidak selalu sinkron dengan render, dan setiap listener menambah beban thread utama. Scroll-driven animations
memindahkan seluruh mekanisme itu ke CSS melalui properti animation-timeline
: animasi keyframe biasa dijalankan bukan oleh waktu, melainkan oleh kemajuan gulir. Fitur ini telah dirilis di seluruh browser utama — Firefox mengikuti pada Oktober 2025 — sehingga kini dapat dipakai lintas browser dengan @supports sebagai jaring pengaman untuk browser lama.
Dua Timeline: scroll() dan view() #
Properti animation-timeline mengganti sumber “waktu” animasi. Dua fungsi timeline bawaan mencakup pola paling umum:
@keyframes terisi {
from { transform: scaleX(0); }
to { transform: scaleX(1); }
}
@keyframes muncul {
from { opacity: 0.2; }
to { opacity: 1; }
}
@supports (animation-timeline: view()) {
.kemajuan {
transform-origin: 0 50%;
animation: terisi linear both;
animation-timeline: scroll();
}
.kartu-unggul {
animation: muncul linear both;
animation-timeline: view();
}
}Mari kita telaah kedua timeline itu:
animation-timeline: scroll(): kemajuan animasi mengikuti posisi gulir sebuah scroll container — tanpa argumen, gulir pada root. Elemen.kemajuantumbuh dari 0% ke 100% seiring halaman digulir dari puncak ke dasar; inilah pola bilah kemajuan baca.animation-timeline: view(): kemajuan animasi mengikuti posisi elemen itu sendiri di dalam viewport. Animasi berjalan dari saat elemen mulai masuk layar hingga keluar — untuk.kartu-unggul, opasitas naik dari 0,2 ke 1 selama kartu melintasi layar.animation-fill-mode: both(katabothpada shorthand): menjaga nilai akhir keyframe tetap berlaku di luar rentang animasi, sehingga elemen tidak melompat kembali saat gulir mencapai batas.linear: timing function yang wajib dipilih dengan sadar — tanpa perekaman waktu, easing defaulteasemembuat kecepatan animasi tidak proporsional terhadap gulir.
Blok @supports (animation-timeline: view()) membungkus kedua aturan: di browser yang mendukung, animasi berjalan; di browser lama, elemen tetap tampil normal dengan gaya statisnya — tidak ada yang rusak.
Dua penyetel lanjutan menunggu setelah pola dasar ini. Properti animation-range mengubah rentang kemajuan — misalnya memulai animasi hanya setelah elemen masuk 20% ke dalam viewport alih-alih dari tepi — dan argumen pada fungsi timeline (scroll() menerima scroll container serta sumbu, view() menerima posisi rentang) menyempitkan sumber kemajuannya. Nilai computed animation-range default tercatat normal; mulailah dari pola di atas, lalu selidiki animation-range di MDN
saat butuh penyetelan itu.
Dampak pada Performa dan Aksesibilitas #
Mengalihkan gerakan ke CSS bukan hanya ringkas, melainkan juga efisien: timeline scroll berjalan di luar thread utama pada browser modern, sehingga animasi tetap lancar meskipun halaman sedang sibuk memproses skrip. Bandingkan dengan listener scroll yang mengantri pekerjaan di thread utama — perbedaannya terasa pada halaman berat.
Sisi aksesibilitasnya menuntut kebiasaan yang telah kita bahas pada Chapter Motion Accessibility
: animasi apa pun yang digerakkan gulir wajib dimatikan bagi pengguna yang memilih gerakan minimum. Karena timeline ini masih animasi CSS biasa, blok @media (prefers-reduced-motion: reduce) tetap menjadi pintu penonaktifannya — tambahkan bersama @supports dari contoh sebelumnya.
Demo: Bilah Kemajuan dan Kartu view() #
<div class="kemajuan" data-expected='{"animation-name":"terisi","animation-timeline":"scroll()"}'></div>
<article class="kartu-unggul" data-expected='{"animation-name":"muncul","animation-timeline":"view()"}'>
Kartu ini memudar masuk saat melintasi viewport.
</article>Hasil di Browser:
Bilah kemajuan berada di puncak halaman dengan animasi "terisi"
pada timeline scroll() — lebarnya menyusuri gulir halaman.
Kartu unggulan membawa animasi "muncul" pada timeline view() —
opasitasnya mengikuti posisi kartu di viewport.
Kedua elemen tercatat pada computed style masing-masing:
animation-name terisi/muncul, animation-timeline scroll()/view().Nilai yang di-claim pada demo tersebut diperiksa otomatis oleh harness melalui atribut data-expected. Uji efeknya secara manual: gulir halaman demo dari atas ke bawah dan amati bilah kemajuan terisi penuh serta kartu semakin pekat saat melintasi layar.