Animasi Performant — Performance

Animasi yang Performant Animasi yang smooth berjalan di 60fps — artinya setiap frame harus selesai dalam 16.6ms. Jika lebih lambat, user melihat "jank"…

Animasi terasa mulus kalau browser bisa menggambar 60 frame tiap detik. Artinya tiap frame harus selesai dalam 16,7 ms (1.000 ms dibagi 60). Kalau satu frame lebih lama, frame itu telat tampil, dan gerakannya patah-patah. Patah-patah ini disebut jank. Bayangin bikin animasi flipbook, buku kecil yang halamannya dibalik cepat. Kalau di tiap halaman kamu menggambar ulang seluruh adegan dari nol, gak keburu. Kalau tokohnya digambar sekali di plastik transparan, lalu di tiap halaman plastiknya cuma digeser, keburu. Menggambar ulang itu left, menggeser plastik itu transform.

🧪 Tebakan cepat: di halaman contoh (1.500 elemen), menggeser kotak pakai left makan 17,0 ms per frame. Kalau diganti transform: translateX(), jadi berapa: 15 ms, 8 ms, atau sekitar 1 ms? Jawabannya ada di bagian "left atau transform, frame demi frame".

60 frame per detik

Layar biasa menampilkan gambar baru 60 kali per detik. Di sela itu browser punya waktu 16,7 ms untuk menyiapkan frame berikutnya: menjalankan Style, Layout, Paint, dan Composite yang kamu kenal dari pelajaran CSS & Rendering Pipeline.

left atau transform, frame demi frame

Lab menggeser kotak bolak-balik di halaman yang punya 1.500 elemen. Ini biaya satu frame (angka simulasi untuk HP kelas menengah):

Tahap left transform: translateX()
Style 0,5 ms 0,5 ms
Layout 12,0 ms dilewati
Paint 4,0 ms dilewati
Composite 0,5 ms 0,5 ms
Total 17,0 ms, lewat 16,7 ms, jadi 30 fps 1,0 ms, 60 fps

Itu jawaban tebakannya: sekitar 1 ms. left mengubah posisi di layout, jadi browser menghitung ulang Layout seluruh halaman dan mengecat ulang area yang berubah di tiap frame. transform gak menyentuh layout: kotak digambar sekali ke lapisannya sendiri (layer), dan tiap frame GPU cuma menggeser lapisan itu.

Biaya Layout ikut naik dengan jumlah elemen. Di Lab hitungannya 0,008 ms per elemen: halaman 600 elemen, left cuma 9,8 ms dan masih lolos. Halaman 3.000 elemen, left 29,0 ms. Biaya transform tetap 1,0 ms berapa pun elemennya.

Satu keuntungan lagi: animasi CSS untuk transform dan opacity bisa dijalankan compositor, di luar main thread. Jadi animasinya tetap mulus walau main thread sedang sibuk menjalankan JavaScript.

Kode: kotak geser yang mulus

<style>
  .box {
    width: 100px;
    height: 100px;
    background: #2563eb;
    will-change: transform;
    animation: geser 2s ease-in-out infinite alternate;
  }

  @keyframes geser {
    from {
      transform: translateX(0);
    }
    to {
      transform: translateX(200px);
    }
  }
</style>

<div class="box"></div>

Versi yang patah-patah cuma beda di isi @keyframes:

.box {
  position: relative;
  animation: geser-buruk 2s ease-in-out infinite alternate;
}

@keyframes geser-buruk {
  from { left: 0; }
  to { left: 200px; } /* Layout dan Paint di tiap frame */
}

Aturan praktis

Mau bikin Pakai Hindari
Geser posisi transform: translate() left, top, margin
Perbesar atau perkecil transform: scale() width, height
Putar transform: rotate()
Muncul atau hilang pelan-pelan opacity visibility, display

will-change: secukupnya

Tiap layer makan memori GPU, kira-kira lebar × tinggi × 4 byte (dikali lagi di layar HP yang kerapatan pikselnya tinggi). Kotak 100 × 100 px cuma 40 KB. Tapi 200 kartu 400 × 300 px yang semuanya diberi will-change butuh sekitar 96 MB. HP murah bisa kehabisan memori, dan halamannya malah jadi lambat.

⚠️ Jebakan yang sering ketemu

TL;DR: Animasi mulus butuh tiap frame selesai dalam 16,7 ms (60 fps). left, top, width, dan height menjalankan Layout dan Paint di tiap frame: di halaman 1.500 elemen, left makan 17,0 ms dan jatuh ke 30 fps. transform dan opacity cukup Composite: 1,0 ms, berapa pun elemennya. Tulis gerakannya di @keyframes dengan transform: translateX(), jalankan dengan animation: geser 2s ... (nama di depan), dan beri will-change: transform hanya di elemen yang memang dianimasikan.

Yang akan kamu pelajari