Animasi dengan @keyframes
Bikin animasi berjalan sendiri tanpa trigger: keyframes, animation shorthand, infinite loop, dan fill mode.
Transisi vs animasi
Transition butuh pemicu (hover, class berubah) dan hanya berpindah dari A ke B. Animation berjalan sendiri, bisa punya banyak tahap (A ke B ke C ke A lagi), dan bisa berulang tanpa henti. Buat loading spinner atau elemen melayang, animation jawabannya.
Menulis @keyframes
@keyframes melayang {
from {
transform: translateY(0);
}
to {
transform: translateY(-12px);
}
}
.balon {
animation: melayang 2s ease-in-out infinite alternate;
}@keyframes mendefinisikan tahap-tahapnya, lalu properti animation menerapkannya ke elemen. infinite = ulang terus, alternate = bolak-balik (tidak patah balik ke awal).
Tahap lebih dari dua
Pakai persen buat banyak keyframe:
@keyframes denyut {
0% { transform: scale(1); opacity: 1; }
50% { transform: scale(1.2); opacity: 0.7; }
100% { transform: scale(1); opacity: 1; }
}
.dot-notifikasi {
animation: denyut 1.5s ease-in-out infinite;
}Shorthand animation
Urutan: nama | durasi | timing | delay | iteration-count | direction | fill-mode | play-state.
.spinner {
animation: putar 1s linear infinite;
}
@keyframes putar {
to { transform: rotate(360deg); }
}linear penting buat spinner: kalau pakai ease, putarannya tersendat-sendat.
animation-fill-mode
Mengatur keadaan sebelum/sesudah animasi:
none(default): kembali ke style normal setelah selesaiforwards: tetap di keyframe terakhir setelah selesaibackwards: pakai keyframe pertama selama masa delayboth: gabungan forwards + backwards
.muncul {
opacity: 0;
animation: fadeNaik 0.5s ease-out forwards;
}
@keyframes fadeNaik {
from { opacity: 0; transform: translateY(20px); }
to { opacity: 1; transform: translateY(0); }
}Dengan forwards, elemen tetap terlihat setelah animasi selesai (tidak balik transparan).
Contoh: skeleton loading
.skeleton {
background: linear-gradient(90deg, #e2e8f0 25%, #f1f5f9 50%, #e2e8f0 75%);
background-size: 200% 100%;
animation: geser 1.5s linear infinite;
}
@keyframes geser {
to { background-position: -200% 0; }
}Efek shimmer loading yang dipakai aplikasi modern, murni CSS tanpa gambar.
Catatan teknis: hormati pengguna yang sensitif gerak. Bungkus animasi non-esensial dalam media query ini dan sediakan versi diamnya:
css@media (prefers-reduced-motion: reduce) { *, *::before, *::after { animation-duration: 0.01ms !important; transition-duration: 0.01ms !important; } }
Rangkuman
@keyframes mendefinisikan tahap animasi, properti animation menjalankannya. Kuasai infinite, alternate, fill-mode forwards, dan timing linear buat putaran. Selalu sediakan versi reduced-motion buat aksesibilitas.