Petunjuk dan konteks
Sebuah produk menginginkan transisi yang koheren antara tampilan daftar, detail, dan filter tanpa mengorbankan navigasi native, aksesibilitas, atau performa perangkat low-end. Rancang rencana progressive enhancement: gunakan document.startViewTransition() untuk pembaruan same-document, deklarasi CSS untuk navigasi cross-document, dan jelaskan perilaku saat API tidak tersedia, pembaruan DOM gagal, atau pengguna memilih reduced motion.
Ini cocok untuk peran frontend, design system, dan performa. MDN, Chrome for Developers, dan spesifikasi CSS View Transitions mendefinisikan siklus hidup ViewTransition, mekanisme same-document dan cross-document, pohon animasi pseudo-element, serta perilaku skip. Artikel ini diturunkan dari standar publik, bukan klaim tentang bank soal wawancara suatu perusahaan.
Hal yang dievaluasi pewawancara
Pewawancara menguji apakah Anda memisahkan semantik navigasi, pembaruan DOM, siklus hidup animasi, dan batasan fallback. Jawaban yang kuat menyebutkan ready, updateCallbackDone, finished, skipTransition(), prefers-reduced-motion, nilai view-transition-name yang unik, dan batasan same-origin. Jawaban yang lemah menambahkan aturan CSS fade-in tanpa rencana penanganan kegagalan.
Pertanyaan klarifikasi
- Apakah targetnya adalah perubahan state SPA, navigasi cross-document, atau keduanya?
- Elemen mana yang membutuhkan identitas bersama, dan apakah kartu daftar memiliki ID stabil saat membuka detail?
- Haruskah navigasi inti dan pengindeksan berfungsi tanpa JavaScript?
- Berapa durasi animasi, anggaran perangkat low-end, dan persyaratan reduced-motion yang dimiliki produk?
Jawaban 30 detik
“Saya akan mempertahankan navigasi native dan pembaruan state sebagai sumber kebenaran (source of truth) serta menggunakan View Transitions sebagai progressive enhancement. Untuk SPA, bungkus pembaruan DOM sinkron atau asinkron dalam startViewTransition(update) dan animasikan pseudo-element setelah ready; untuk navigasi multi-halaman, gunakan @view-transition { navigation: auto; } same-origin dengan nama stabil untuk elemen bersama. Jika API tidak ada, pembaruan gagal, atau reduced motion diminta, selesaikan pembaruan tanpa animasi dan panggil skipTransition() saat diperlukan. Nama yang unik, batas waktu (timeout), dan metrik mencegah transisi memblokir perilaku produk.”
Solusi langkah demi langkah
Untuk transisi same-document, panggil document.startViewTransition(() => update()). Peramban menangkap state lama, menjalankan callback pembaruan, dan membuat state baru; ViewTransition yang dikembalikan mengekspos Promise ready, updateCallbackDone, dan finished. Jika callback melempar error, aplikasi tetap memegang kendali penanganan kesalahan; pengiriman data bisnis tidak boleh bergantung pada keberhasilan animasi. Kustomisasi transisi dengan pseudo-element seperti ::view-transition-old(root) dan ::view-transition-new(root).
Gunakan view-transition-name untuk memasangkan elemen lama dengan pasangannya yang baru. Nama harus unik dalam satu pohon transisi. Daftar memerlukan ID bisnis yang stabil daripada indeks array, jika tidak, pengurutan atau pemfilteran akan memasangkan elemen yang salah. Beri nama hanya pada elemen-elemen penting; terlalu banyak snapshot dan permukaan compositor meningkatkan beban komputasi.
Transisi cross-document mengandalkan navigasi same-origin dan deklarasi CSS @view-transition; JavaScript tidak memanggil startViewTransition() untuk navigasi tersebut. Ini berfungsi untuk aplikasi multi-halaman tetapi bergantung pada dukungan peramban, kebijakan same-origin, dan CSS halaman. Tautan harus tetap dapat bernavigasi secara normal tanpa transisi; Promise animasi tidak boleh memblokir respons server atau perilaku tautan default.
Penanganan siklus hidup membutuhkan jalur timeout dan skip. Jika ready tidak selesai (settle) dalam batas waktu yang ditentukan, catat alasannya dan panggil skipTransition(). Navigasi kembali (back navigation), pengiriman formulir, dan meninggalkan halaman harus memprioritaskan navigasi. Gunakan finished hanya untuk pembersihan dan metrik, jangan pernah sebagai bukti bahwa data telah disimpan. Untuk data asinkron, tentukan batas commit state sebelum memutuskan apakah akan menunggu transisi.
Aksesibilitas berarti menghormati @media (prefers-reduced-motion: reduce) dengan mengatur durasi animasi ke nol atau melewatinya. Pertahankan fokus, heading, dan urutan membaca; posisi visual tidak dapat menggantikan pembaruan semantik. Pengguna keyboard, pembaca layar, dan perangkat lambat harus menerima hasil konten yang sama persis.
Progressive enhancement menggabungkan deteksi kemampuan dengan fallback navigasi nyata. Jika document.startViewTransition tidak ada, panggil fungsi pembaruan secara langsung; jika dukungan cross-document tidak ada, pertahankan tautan biasa. Ukur tingkat dukungan, tingkat skip, latensi ready, frame rate, dan latensi interaksi berdasarkan peramban dan perangkat. Transisi boleh mengubah presentasi, tetapi tidak boleh mengubah kebenaran cache, izin, pengiriman formulir, atau routing.
Jawaban model
Saya akan memisahkan navigasi dan pengiriman state dari animasi. SPA menggunakan startViewTransition(update) dan menganimasikan hanya elemen bersama yang penting setelah ready; aplikasi multi-halaman menggunakan @view-transition same-origin. Setiap elemen bersama mendapatkan nama bisnis yang stabil dan unik, serta pembaruan asinkron yang gagal akan melewati transisi sambil menampilkan status error normal.
Peramban yang tidak didukung akan menggunakan pembaruan native atau tautan biasa. Pengguna dengan preferensi reduced-motion tidak menerima animasi atau mendapatkan animasi yang dipersingkat. Batas waktu siklus hidup mempertahankan skipTransition(). Fokus, heading, dan urutan semantik tidak pernah bergantung pada efek visual. Pantau dukungan, skip, dan latensi interaksi, lalu perluas set elemen bernama setelah rilis canary.
Kesalahan umum
- Kesalahan → menggunakan indeks array sebagai
view-transition-name; Mengapa gagal → pengurutan memasangkan node lama dan baru yang salah; Perbaikan → gunakan ID bisnis yang stabil dan tegakkan keunikan. - Kesalahan → menunggu
finishedsebelum mengirimkan formulir; Mengapa gagal → kegagalan animasi memblokir tindakan bisnis; Perbaikan → commit state terlebih dahulu dan hanya animasikan presentasi. - Kesalahan → hanya merancang jalur SPA; Mengapa gagal → navigasi multi-halaman tidak memiliki titik pemanggilan JavaScript; Perbaikan → gunakan
@view-transitionsame-origin dan pertahankan tautan biasa. - Kesalahan → mengabaikan preferensi reduced-motion; Mengapa gagal → pengguna yang sensitif dapat mengalami pusing atau beban kognitif; Perbaikan → persingkat atau lewati animasi dalam media query.
Pertanyaan lanjutan
Bagaimana callback pembaruan yang gagal memengaruhi transisi dan state?
Perlakukan callback pembaruan sebagai batasan state bisnis: tangkap eksepsi, lakukan rollback atau render error, dan batasi Promise transisi hanya pada siklus hidup animasi. Jika updateCallbackDone menolak (reject), panggil skipTransition() atau biarkan peramban menyelesaikan presentasi default; jangan menelan error tersebut.
Mengapa tidak menamai setiap elemen sebagai elemen bersama?
Setiap nama harus membentuk pasangan yang tidak ambigu antara pohon lama dan baru. Menamai semua hal meningkatkan biaya penangkapan layar (capture), tata letak (layout), dan komposisi, serta dapat menciptakan kecocokan yang tidak disengaja. Beri nama hanya pada objek-objek utama yang dipahami pengguna; gunakan root fade atau tanpa animasi untuk sisanya.
Bagaimana Anda membuktikan bahwa transisi tidak merusak performa?
Ukur latensi ready, frame rate, long task, latensi first-input, dan tingkat skip berdasarkan peramban dan perangkat, lalu uji ukuran daftar yang realistis. Jika perangkat low-end menunjukkan penurunan frame rate yang berkelanjutan, kurangi cakupan animasi atau lewati secara otomatis sambil menjaga waktu navigasi tetap tidak berubah.