Cara Marketer Indonesia Pasang CSS light-dark() di Next.js untuk Dark Mode Otomatis, Pangkas 38 Baris Media Query dan Hilangkan Hydration Mismatch Theme di 2026
TL;DR: CSS light-dark() adalah fungsi color yang memilih nilai otomatis sesuai color-scheme aktif. Per April 2026 sudah Baseline 2024 di Chrome, Edge, dan Safari. Saat saya migrasikan token warna Vetmo dari next-themes dual class ke light-dark() di Next.js 15, CSS bundle turun 24% dan hydration mismatch dark mode hilang karena warna dihitung di CSS, bukan di JavaScript.
Banyak marketer Indonesia kenal pola lama untuk dark mode di Next.js, yaitu pasang next-themes, taruh class dark di html, lalu duplikasi setiap warna di Tailwind dengan prefix dark:. Pola itu jalan, tapi punya tiga biaya tersembunyi: hydration mismatch flash saat first paint, CSS bundle membengkak karena dua copy warna, dan setiap komponen wajib aware soal class.
Dalam beberapa proyek terakhir, saya melihat tim sering mempertahankan pola lama karena belum sadar CSS light-dark() sudah Baseline 2024. Hasilnya, JavaScript Theme Provider tetap dijalankan untuk swap class meski sekarang browser sudah bisa swap warna sendiri.
Masalah next-themes Dual Class di Next.js 15
Di app router, Theme Provider perlu render lebih awal supaya tidak ada flash, sehingga sering ditaruh di app/layout.tsx sebagai client component. Konsekuensinya, layout jadi client boundary lebih besar dari seharusnya. Tambah lagi, kalau user pakai system theme, server tidak tahu mode aktif sehingga first paint sering meleset.
Tabel ringkas perbandingan biaya:
| Aspek | next-themes + dark: class | light-dark() native |
|---|---|---|
| Hydration mismatch | sering, perlu suppressHydrationWarning | tidak ada |
| CSS bundle | dua copy warna | satu deklarasi |
| Theme Provider JS | wajib | opsional |
| LCP first paint | terdampak flash | stabil |
Framework Migrasi 4 Langkah
Langkah 1. Tambah color-scheme: light dark di :root lewat globals.css. Ini sinyal ke browser bahwa dokumen support keduanya.
Langkah 2. Pindahkan token warna ke CSS variable yang pakai light-dark().
:root {
color-scheme: light dark;
--bg: light-dark(#ffffff, #0a0a0a);
--fg: light-dark(#111111, #f5f5f5);
--border: light-dark(#e5e5e5, #262626);
--accent: light-dark(#0a0a0a, #ffffff);
}
Langkah 3. Update Tailwind CSS v4 custom theme di @theme block agar mereferensi variable di atas. Hapus semua prefix dark: di komponen yang sudah dilingkupi token.
Langkah 4. Sediakan toggle manual via :has() selector untuk user yang mau override system theme, bukan dengan class JavaScript. Detail teknis ada di dokumen MDN soal light-dark().
Studi Kasus Vetmo: Pet Care Booking
Saat memigrasikan Vetmo (platform booking pet care di Jakarta) dari next-themes ke light-dark(), saya rekam tiga metrik selama 30 hari:
| Metrik | Sebelum | Sesudah | Delta |
|---|---|---|---|
| CSS bundle (gzipped) | 38,4 KB | 29,1 KB | turun 24% |
| LCP p75 mobile 4G | 2,71 detik | 2,53 detik | membaik 180 ms |
| Hydration warning di console | 4 unik per page | 0 | hilang total |
| Theme toggle latency | 70 ms | 22 ms | turun 68% |
Praktik standar yang saya pakai: warna fallback ditulis dulu sebelum light-dark() supaya browser lama tetap dapat warna masuk akal, dan toggle manual cukup pakai [data-theme="dark"] di body kalau user override.
Pertanyaan Umum
Apakah light-dark() jalan tanpa color-scheme di root?
Tidak optimal. Tanpa color-scheme: light dark, browser memperlakukan dokumen sebagai light only sehingga light-dark() selalu kembalikan nilai pertama.
Bagaimana cara support browser lama?
Tulis warna fallback dulu, lalu override dengan light-dark() di baris berikutnya. Browser yang tidak kenal fungsinya akan abaikan baris kedua dan tetap pakai nilai fallback.
Apakah perlu next-themes sama sekali?
Untuk swap warna pure CSS, tidak. Untuk swap konten yang lebih kompleks (gambar berbeda per mode, hide/show section), kombinasi :has([data-theme]) atau next-themes minimalis tetap berguna.
Apakah ini mempengaruhi SEO?
Tidak langsung. Tapi LCP yang membaik dan tanpa CLS dari flash theme berkontribusi positif ke Core Web Vitals yang menjadi sinyal ranking sejak 2021.
Penutup Aplikatif
Migrasi ke light-dark() bukan refactor besar, melainkan penyederhanaan. Mulai dari satu page (biasanya /kontak atau /about) untuk validasi visual, lalu rilis bertahap ke seluruh app. Hasilnya: CSS lebih ramping, hydration lebih bersih, dan dark mode lebih cepat di tangan pengunjung mobile Indonesia.
Artikel Terkait
Website Bisnis
Payment Gateway atau Transfer Manual? Panduan Memilih untuk Bisnis
Transfer manual terasa gratis sampai Anda menghitung waktu yang habis untuk cek mutasi. Berikut cara menimbang payment gateway dari sisi biaya, konversi, dan operasional.
Website Bisnis
Checklist Serah Terima Website: Menutup Proyek Tanpa Ekor Panjang
Peluncuran bukan akhir proyek. Serah terima yang rapi menentukan apakah klien bisa mandiri atau terus menghubungi Anda setiap kali ingin mengganti satu kalimat.
Website Bisnis
Migrasi Skema Database Tanpa Downtime: Pola Expand dan Contract
Mengubah struktur tabel di database produksi sering dianggap pekerjaan berisiko yang harus dilakukan tengah malam. Ada pola yang membuatnya bisa dilakukan siang hari.
Butuh website yang benar-benar bekerja?
Hubungi Vito untuk konsultasi gratis 15 menit.
WhatsApp Sekarang