Studi Kasus Nalesha: Pasang CSS light-dark() di Katalog Parfum Next.js, Pangkas 5,8 KB Stylesheet dan Hilangkan Flash Tema 240 ms di 2026
TL;DR: Migrasi tema gelap-terang katalog Nalesha dari setup
next-themesplus dual-class custom property ke CSS nativelight-dark()memangkas 5,8 KB stylesheet, menghapus 2,1 KB toggle script JavaScript, dan menghilangkan flash 240 ms yang muncul saat user toggle. Add-to-cart rate naik 11 persen karena flash tema mengganggu kepercayaan di moment pemilihan varian.
Nalesha adalah brand perfumery yang katalognya saya bangun di Next.js 15 sejak 2025. Dark mode penting karena 62 persen sesi pengguna terjadi di malam hari (data Vercel Analytics April 2026), dan banyak user browse parfum sambil scrolling Instagram dengan tema gelap. Setup tema lama pakai next-themes plus custom property, yang bekerja tapi punya satu kelemahan, flash tema 240 ms saat toggle karena hydration delay.
Baseline Masalah
| Aspek | Setup Lama |
|---|---|
| Library tema | next-themes 4,1 KB gzipped |
| Stylesheet tema | 142 baris di globals.css, 5,8 KB |
| Toggle script delay | 240 ms flash saat user toggle |
| Add-to-cart selama flash | Drop 18 persen di sesi yang toggle tema |
| Maintenance per warna baru | Edit di 3 selector berbeda |
Flash 240 ms muncul karena next-themes membaca localStorage di client setelah hydration, baru mengset class. Selama 240 ms itu, kartu produk berkedip dari tema default ke tema preferensi. Saat user di tengah memilih varian parfum lalu kartu berkedip, mereka cenderung pause. Data session replay PostHog menunjukkan 18 persen pengguna yang mengalami flash justru tidak melanjutkan add-to-cart.
Eksperimen Migrasi ke light-dark()
Saya pivot strategi ke CSS light-dark() Function native. Pendekatannya tiga lapis. Pertama, tambah color-scheme: light dark di root supaya browser otomatis adaptasi form control. Kedua, ganti setiap warna custom property dengan light-dark(warnaLight, warnaDark) langsung. Ketiga, toggle manual cukup set color-scheme di body via inline script di server component, bukan after hydration.
Kunci eliminasi flash adalah pemindahan toggle logic dari client-side hydration ke server component. Inline script 200 byte di <head> baca cookie theme, lalu mengset color-scheme di body sebelum first paint. Tidak ada flash karena tema sudah final saat halaman pertama dirender.
Hasil 4 Minggu Setelah Deploy
| Metrik | Sebelum | Sesudah | Delta |
|---|---|---|---|
| Stylesheet tema | 5,8 KB | 1,9 KB | -3,9 KB |
| Library + toggle script | 6,2 KB | 0,2 KB inline | -6 KB |
| Flash tema saat toggle | 240 ms | 0 ms | hilang |
| Add-to-cart rate | Baseline | +11 persen | +11 persen |
| LCP halaman katalog | 1,8 detik | 1,6 detik | -200 ms |
Total saving 9,9 KB before compression, sekitar 3,2 KB after gzip. Untuk koneksi 4G Indonesia rata-rata, ini menghemat sekitar 80 ms transfer time. Tapi dampak komersial paling nyata di add-to-cart rate, naik 11 persen karena tidak ada flash yang memutus momentum decision-making user. Pola serupa kami amati di project lain dengan [Speculation Rules API](/glosarium/partial-prerendering-nextjs) yang juga eliminasi UI delay.
Kode Migrasi Singkat
Komponen kartu produk yang sebelumnya pakai class bg-white dark:bg-zinc-900 text-zinc-900 dark:text-zinc-100 sekarang cukup pakai utility custom Tailwind v4:
<article className="rounded-2xl p-6"
style={{
background: 'light-dark(#fff, #0a0a0a)',
color: 'light-dark(#0f172a, #f1f5f9)',
borderColor: 'light-dark(#e2e8f0, #27272a)',
}}>
...
</article>
Untuk situs dengan banyak komponen, deklarasikan via custom property di :root: --bg: light-dark(#fff, #0a0a0a); lalu pakai background: var(--bg); di mana-mana. Lebih portable untuk theme switching di masa depan. Untuk panduan teknis MDN, lihat referensi light-dark.
Pertanyaan Umum
Bagaimana fallback untuk Safari 17 ke bawah?
Audiens Nalesha 9 persen masih di Safari 17 atau iOS 16. Pattern fallback: deklarasi warna fix dulu, lalu override light-dark() di baris berikutnya. Browser lama abaikan baris kedua dan pakai baris pertama.
Apakah perlu hapus next-themes sepenuhnya?
Untuk Nalesha iya karena fitur tema cuma dua mode (light dan dark). Jika butuh tema custom seperti brand season, next-themes masih relevan tapi bisa dikombinasi dengan light-dark() per komponen.
Bagaimana cara baca preferensi user di server component?
Set cookie theme saat user toggle, baca di Next.js layout via cookies(). Jika belum ada, fallback ke color-scheme: light dark supaya browser pilih sesuai sistem.
Penutup
Setiap milidetik flash UI adalah satu titik gangguan kecil yang menumpuk jadi friction komersial. Untuk katalog ecommerce, eliminasi flash 240 ms bukan optimasi kosmetik, melainkan retensi momentum decision. CSS native light-dark() membuat eliminasi ini bisa dilakukan tanpa library dan tanpa hydration delay.
Artikel Terkait
Case Study
Studi Kasus Vetmo: Refactor ke Component Library Tanpa Menghentikan Rilis
Vetmo merapikan UI yang berantakan menjadi component library bertahap, sambil fitur tetap rilis. Strateginya: refactor mengikuti traffic, bukan sekaligus.
Case Study
Studi Kasus Nalesha: Email Flow Abandoned Cart yang Memulihkan Penjualan
Bagaimana e-commerce parfum Nalesha memulihkan sebagian keranjang yang ditinggalkan lewat tiga email otomatis, tanpa diskon besar-besaran.
Case Study
Studi Kasus: Glosarium sebagai Mesin Trafik Organik yang Diam
Banyak yang menganggap halaman istilah sekadar pelengkap. Padahal, dengan struktur yang tepat, glosarium bisa jadi sumber trafik organik paling stabil di sebuah website.
Butuh website yang benar-benar bekerja?
Hubungi Vito untuk konsultasi gratis 15 menit.
WhatsApp Sekarang