Transitions cuma bisa A → B (warna biru jadi hitam, posisi 0 jadi 100). Tapi pas kamu pengen elemen geleng-geleng kepala kayak nolak (kanan-kiri-kanan-kiri-tengah)? Itu butuh banyak titik tahap, bukan cuma 2. CSS Animations + @keyframes kasih kamu kontrol penuh per tahap — kayak bikin video stop-motion: kamu definisikan frame penting, browser interpolate frame-frame antaranya jadi gerakan halus.
💡 Pembeda profesional vs amatir. Web yang dipenuhin animasi norak = amatir. Web yang animasinya "tepat di momen yang tepat" (modal slide-in pas dibuka, error message shake kecil pas validasi gagal) = profesional. Animation jago bukan soal seberapa banyak, tapi soal kapan dan kenapa.
Mendefinisikan keyframes:
@keyframes geser-kanan {
from {
transform: translateX(0);
}
to {
transform: translateX(200px);
}
}
Bisa juga menggunakan persentase untuk lebih dari 2 tahap:
@keyframes warna-berubah {
0% { background: red; }
50% { background: yellow; }
100% { background: green; }
}
Menggunakan animasi pada elemen:
.kotak {
animation-name: geser-kanan;
animation-duration: 2s;
animation-timing-function: ease;
animation-delay: 0s;
animation-iteration-count: infinite;
animation-direction: alternate;
}
/* Shorthand */
.kotak {
animation: geser-kanan 2s ease infinite alternate;
}
Properti animation:
animation-iteration-count— jumlah pengulangan (angka atauinfinite)animation-direction— arah (normal, reverse, alternate)animation-fill-mode— keadaan sebelum/sesudah animasi (forwards, backwards, both)animation-play-state— pause/resume (running, paused)
🎭 Analogi sehari-hari
animation + @keyframes = menyusun video stop-motion. Kamu gambar setiap frame penting (0%, 50%, 100%), browser interpolate yang di antaranya. Beda sama transition yang cuma dari A ke B, animation bisa multi-tahap + loop.
⚠️ Jebakan yang sering ditemui
- Lupa
animation-name= tidak jalan. Atau nama tidak match@keyframes. animation-fill-mode: forwards= elemen STAY di state akhir setelah animasi selesai. Tanpa ini, balik ke state awal.- Infinite animation boros battery + CPU. Pakai
prefers-reduced-motionuntuk respect user. @keyframesHARUS punyafrom/toatau0%/100%. Tanpa endpoint = animation tidak ada.- Animation di element
display: none= tidak jalan (browser skip rendering). will-change: transformberi hint browser optimize — pakai sparingly, kalau abuse bisa malah lag.- Tidak bisa pause via CSS sendiri —
animation-play-state: pausedperlu ganti via class/state.
🎯
transitionvsanimation— pilih yang mana?
- State change A → B (hover, click, focus) →
transition(1 baris CSS, simpel)- Multi-tahap (loading spinner, geleng-geleng error, fade-in slide) →
animation+@keyframes- Loop terus (skeleton shimmer, pulse) →
animationdenganinfinite- Reverse otomatis pas state berubah balik →
transition(animation perlu logika manual)Aturan: kalau bisa diselesaikan pake
transition, pake itu — lebih murah, lebih declarative.animationcuma kalau butuh tahap-tahap atau loop.
TL;DR: Animation = multi-tahap gerakan terkontrol via @keyframes (definisi frame) + animation property (cara jalan). Beda transition: animation bisa banyak tahap (0%/50%/100%) + loop (infinite) + auto-reverse (alternate). Pakai animation-fill-mode: forwards biar stay di state akhir. Hormati prefers-reduced-motion (accessibility). Pilih transition kalau cukup A → B, animation kalau butuh tahap atau loop.