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:

css
@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:

  1. animation-timeline: scroll(): kemajuan animasi mengikuti posisi gulir sebuah scroll container — tanpa argumen, gulir pada root. Elemen .kemajuan tumbuh dari 0% ke 100% seiring halaman digulir dari puncak ke dasar; inilah pola bilah kemajuan baca.
  2. 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.
  3. animation-fill-mode: both (kata both pada shorthand): menjaga nilai akhir keyframe tetap berlaku di luar rentang animasi, sehingga elemen tidak melompat kembali saat gulir mencapai batas.
  4. linear: timing function yang wajib dipilih dengan sadar — tanpa perekaman waktu, easing default ease membuat 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() #

html index.html
<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:

text
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.