Pedoman animasi UX & performa 2025 — Ringkas dan praktis
Diterbitkan: 20 Sep 2025 · Waktu baca: 4 mnt · Redaksi Unified Image Tools
Mengapa tinggalkan GIF
GIF tidak efisien, kualitas rendah, dan terbatas warna. Tahun 2025: gunakan WebP/AVIF animasi untuk loop/UI, dan MP4/WebM pendek untuk video dengan audio/foto nyata.
Pemilihan format
- Loop pendek / animasi UI: WebP/AVIF animasi
- Rekaman nyata/foto + audio: MP4/WebM (video)
- Butuh transparansi: WebP animasi (cek dukungan transparansi AVIF di browser)
Pola implementasi
<video autoplay loop muted playsinline width="640" height="360" preload="metadata">
<source src="/loop.webm" type="video/webm" />
<source src="/loop.mp4" type="video/mp4" />
<!-- Gambar fallback -->
<img src="/loop.jpg" alt="loop pendek" />
</video>
Tips perancangan pengalaman
- Hormati
prefers-reduced-motion
(sediakan opsi berhenti via CSS/JS). - Jangan blok FCP/LCP: muat tepat sebelum interaksi.
- Thumbnail sebagai gambar statis; saat diputar baru muat animasi/video.
Kurangi gerak via CSS
@media (prefers-reduced-motion: reduce) {
.anim { animation: none !important; transition: none !important; }
}
Berpikir anggaran (performa & data)
- Video hero di kisaran 500–800KB (atau poster statis + putar tertunda untuk kualitas).
- Hindari banyak pemutaran bersamaan; fokus satu instance lewat aksi pengguna.
- Mobile: anggap
preload="none"
; setelsrc
setelah interaksi.
Checklist
- [ ] Migrasi GIF → WebP/AVIF/video
- [ ] Susun kebutuhan transparansi/loop
- [ ] Dukung
prefers-reduced-motion
- [ ] Optimalkan lazy‑load dan cache
Studi kasus
- Indikator loading: ganti dengan CSS animation, hemat ~30KB.
- Hero animation jadi video: 2.4MB GIF → 420KB WebM (kualitas visual sebanding).
- Pemicu saat scroll: injeksi
src
pada 30% terlihat (IntersectionObserver).
FAQ
-
Q: Lebar layar berapa video harus berhenti?
-
A: Pertimbangkan bandwidth/baterai; di mobile autoplay harus pendek dan tanpa suara. Putar penuh dengan aksi pengguna.
-
Q: WebP vs AVIF?
-
A: AVIF umumnya kompresi lebih baik; sertakan WebP untuk kompatibilitas.
-
Q: Dampak SEO?
-
A: Jangan merusak LCP/CLS. Hindari autoplay di hero; gunakan poster statis + putar tertunda.
-
Q: Subtitle/aksesibilitas?
-
A: Video bermakna perlu subtitle; dukung keyboard/stop/volume.
Prinsip desain — Gerak yang bermakna
- Makna: batasi gerak untuk transisi status/sebab‑akibat/hirarki.
- Aman: hindari kedipan >3Hz dan zoom/rotasi ekstrem (WCAG 2.3.1).
- Konsisten: komponen yang sama → waktu/easing yang sama.
- Dapat dibalik: jika gagal, UI statis tetap fungsional.
Waktu & easing — patokan
- Transisi kecil: 120–180ms /
cubic-bezier(0.2, 0, 0, 1)
- Kontainer/modal: 180–240ms /
ease-out
- Transisi halaman (crossfade/slide): 240–320ms /
ease-in-out
- Pegas (fisik):
damping: 20–28, stiffness: 140–220
.btn {
transition: transform 160ms cubic-bezier(.2,0,0,1), box-shadow 160ms ease-out;
}
.btn:active { transform: translateY(1px); }
Web Animations API & pegas
// Hormati Reduced Motion saat memakai WAAPI
const prefersReduced = matchMedia('(prefers-reduced-motion: reduce)').matches;
const el = document.querySelector('.card');
if (!prefersReduced && el) {
el.animate([
{ transform: 'translateY(8px)', opacity: 0 },
{ transform: 'translateY(0)', opacity: 1 },
], {
duration: 220,
easing: 'cubic-bezier(.2,0,0,1)',
fill: 'both'
});
}
// Aproksimasi pegas sederhana
function springTo(el, to = 0, { stiffness = 180, damping = 22 } = {}) {
let v = 0; // velocity
let x = 1; // normalized position
const dt = 1/60;
function frame() {
const f = -stiffness * (x - to) - damping * v;
v += f * dt;
x += v * dt;
el.style.transform = `translateY(${x * 20}px)`;
if (Math.abs(v) > 0.001 || Math.abs(x - to) > 0.001) requestAnimationFrame(frame);
}
frame();
}
Optimasi terkait scroll
- Mulai pada 25–33% terlihat di viewport (IntersectionObserver).
- Manfaatkan
position: sticky
; minimalisir perhitungan JS untuk parallax/pin. - Utamakan
transform/opacity
ketimbang properti mahal (top/left/width/height).
const io = new IntersectionObserver(entries => {
entries.forEach(e => {
if (e.isIntersecting) e.target.classList.add('in');
});
}, { threshold: 0.3 });
document.querySelectorAll('.reveal').forEach(n => io.observe(n));
Lottie / CSS / Video — penggunaan
- Lottie (JSON vektor): ikon UI/ilustrasi ringan; ganti warna/independen resolusi.
- CSS: mikro‑interaksi; dependensi ringan, biaya eksekusi rendah.
- Video: kualitas foto/ekspresi kompleks; kompresi efisien, subtitle/audio mungkin.
Aturan: “prioritas kualitas → Video”, “loop UI ringan → CSS/Lottie”, “butuh transparansi → Lottie/WebP animasi”.
Pengukuran performa
// Pahami dampak pada paint/compose
new PerformanceObserver((list) => {
for (const e of list.getEntries()) {
console.log(e.entryType, e.name, e.duration);
}
}).observe({ entryTypes: ['longtask', 'measure'] });
performance.mark('anim:start');
// ... run animation ...
performance.mark('anim:end');
performance.measure('anim:duration', 'anim:start', 'anim:end');
Aksesibilitas/keamanan
- Sediakan stop/jeda/sembunyikan (WCAG 2.2.2).
prefers-reduced-motion
dengan alternatif; autoplay default tanpa suara.- Hindari kedipan 3Hz–60Hz; kendalikan kontras terang.
Implementasi tahan‑gagal — cek
- [ ] Tujuan & KPI (CTR/durasi baca/selesai baca …)
- [ ] Gerak hanya transform/opacity (tanpa reflow layout)
- [ ] Lazy‑load/pemicu aksi pengguna
- [ ] Aturan Reduced Motion & UI stop manual
- [ ] Uji A/B untuk validasi efek
FAQ lanjutan
-
Q: Apakah Lottie bisa jadi berat?
- A: Kurangi primitives dan optimalkan framerate; jika tetap berat, pindah ke video.
-
Q: Kapan GIF tak terhindarkan?
- A: Hanya saat ada tuntutan kompatibilitas kuat. Sadari kompromi ukuran/kualitas dan batasi.
-
Q: Animasi terkait scroll terasa patah
- A: Kombinasikan
requestAnimationFrame
dan IntersectionObserver, kurangi beban thread, dan jangan berlebihan memakaiwill-change
.
- A: Kombinasikan
Artikel terkait
Dasar-dasar optimasi gambar 2025 — Fondasi andal tanpa tebak-tebakan
Dasar terbaru untuk pengantaran gambar yang cepat dan indah di situs apa pun. Urutannya: Ubah ukuran → Kompres → Responsif → Cache untuk operasi yang stabil.
Prioritas pengiriman gambar 2025 — fetchpriority, preload
Kendalikan LCP dengan `fetchpriority`, `preload`, ukuran responsif, dan anggaran bandwidth. Strategi per jenis halaman.