Mengimplementasikan Dark Mode: Panduan Lengkap untuk Developer
Embed This Widget
Add the script tag and a data attribute to embed this widget.
Embed via iframe for maximum compatibility.
<iframe src="https://colorfyi.com/iframe/entity//" width="420" height="400" frameborder="0" style="border:0;border-radius:10px;max-width:100%" loading="lazy"></iframe>
Paste this URL in WordPress, Medium, or any oEmbed-compatible platform.
https://colorfyi.com/entity//
Add a dynamic SVG badge to your README or docs.
[](https://colorfyi.com/entity//)
Use the native HTML custom element.
Dark mode telah bergeser dari preferensi niche menjadi fitur yang diharapkan. Pengguna di setiap platform — macOS, Windows, Android, iOS — dapat mengatur tampilan gelap di seluruh sistem, dan mereka mengharapkan situs web serta aplikasi untuk menghormatinya. Mengimplementasikan dark mode dengan benar membutuhkan lebih dari sekadar mengganti putih dengan hitam: diperlukan pendekatan sistematis terhadap warna, kontras, dan kontrol pengguna. Panduan ini membahas proses lengkapnya, mulai dari arsitektur CSS hingga mekanika toggle JavaScript hingga pengujian kedua tema secara menyeluruh.
CSS Custom Properties untuk Tema
Cara paling mudah dikelola untuk menangani dark mode dalam CSS adalah melalui custom properties (disebut juga CSS variables). Alih-alih menyebarkan nilai warna di seluruh stylesheet, Anda mendefinisikan setiap warna sebagai variabel di :root lalu mendefinisikan ulang variabel tersebut untuk dark mode. Style komponen hanya merujuk pada variabel — tidak pernah pada kode hex mentah.
Mendefinisikan Palet Terang dan Gelap Anda
Mulailah dengan palet light mode sebagai default. Titik awal yang bersih mungkin terlihat seperti ini:
:root {
/* Latar belakang */
--color-bg-base: #FFFFFF;
--color-bg-elevated: #F8F9FA;
--color-bg-overlay: #F1F3F5;
/* Teks */
--color-text-primary: #1A1A2E;
--color-text-secondary: #4A4A6A;
--color-text-muted: #6C757D;
/* Border */
--color-border: #DEE2E6;
--color-border-strong: #ADB5BD;
/* Brand / aksen */
--color-accent: #3B82F6;
--color-accent-hover: #2563EB;
/* Umpan balik */
--color-success: #22C55E;
--color-warning: #F59E0B;
--color-danger: #EF4444;
}
Kemudian definisikan penggantian untuk dark mode dalam blok terpisah. Wawasan utamanya adalah Anda tidak sekadar membalikkan warna — Anda memilih palet berbeda yang dirancang khusus untuk permukaan gelap:
[data-theme="dark"] {
/* Latar belakang */
--color-bg-base: #0F0F17;
--color-bg-elevated: #1A1A2E;
--color-bg-overlay: #252540;
/* Teks */
--color-text-primary: #E8E8F0;
--color-text-secondary: #A8A8C0;
--color-text-muted: #6A6A88;
/* Border */
--color-border: #2E2E4A;
--color-border-strong: #4A4A6A;
/* Brand / aksen — seringkali sedikit lebih terang untuk keterbacaan di latar gelap */
--color-accent: #60A5FA;
--color-accent-hover: #93C5FD;
/* Umpan balik — sedikit desaturasi untuk menghindari kekerasan */
--color-success: #4ADE80;
--color-warning: #FCD34D;
--color-danger: #F87171;
}
Perhatikan bahwa aksen #3B82F6 pada light mode menjadi #60A5FA pada dark mode. Rona-nya sama namun kecerahan meningkat — ini diperlukan karena konteks kontras telah berubah. Warna yang lulus WCAG AA terhadap latar putih hampir selalu gagal terhadap latar mendekati hitam kecuali jika disesuaikan. Shade Generator memungkinkan Anda menjelajahi rentang penuh 50–950 dari warna apa pun, sehingga mudah memilih shade yang tepat untuk setiap tema.
Menggunakan Variabel dalam Komponen
Dengan palet yang sudah ditetapkan, setiap komponen merujuk pada variabel bukan nilai mentah:
.card {
background-color: var(--color-bg-elevated);
border: 1px solid var(--color-border);
color: var(--color-text-primary);
}
.btn-primary {
background-color: var(--color-accent);
color: #FFFFFF;
}
.btn-primary:hover {
background-color: var(--color-accent-hover);
}
Saat atribut [data-theme="dark"] ada pada elemen <html>, semua variabel diperbarui serentak, dan setiap komponen yang merujuknya berubah tampilan — tanpa CSS tambahan sama sekali.
Media Query prefers-color-scheme
Sebelum pengguna berinteraksi dengan toggle, Anda dapat menghormati preferensi sistem operasi mereka menggunakan media query prefers-color-scheme. Media query ini aktif saat OS diatur ke tampilan gelap.
@media (prefers-color-scheme: dark) {
:root {
--color-bg-base: #0F0F17;
--color-bg-elevated: #1A1A2E;
--color-bg-overlay: #252540;
--color-text-primary: #E8E8F0;
--color-text-secondary: #A8A8C0;
--color-text-muted: #6A6A88;
--color-border: #2E2E4A;
--color-border-strong: #4A4A6A;
--color-accent: #60A5FA;
--color-accent-hover: #93C5FD;
--color-success: #4ADE80;
--color-warning: #FCD34D;
--color-danger: #F87171;
}
}
Pendekatan ini bekerja tanpa JavaScript, tidak menyebabkan layout shift, dan langsung menghormati preferensi pengguna saat halaman dimuat. Ini adalah baseline yang tepat. Keterbatasannya adalah pengguna tidak dapat menggantinya di aplikasi Anda — jika OS gelap, situs gelap, tanpa jalan keluar. Itulah mengapa sebagian besar implementasi produksi melapisi toggle JavaScript di atas media query.
Menggabungkan Kedua Pendekatan
Pola yang direkomendasikan menggunakan media query sebagai default dan atribut data-theme sebagai penggantian eksplisit:
/* 1. Default light mode */
:root {
--color-bg-base: #FFFFFF;
/* ... */
}
/* 2. OS dark mode override (saat tidak ada preferensi eksplisit) */
@media (prefers-color-scheme: dark) {
:root:not([data-theme="light"]) {
--color-bg-base: #0F0F17;
/* ... */
}
}
/* 3. Dark mode eksplisit (pengguna toggle via JS) */
[data-theme="dark"] {
--color-bg-base: #0F0F17;
/* ... */
}
Selektor :not([data-theme="light"]) dalam media query berarti preferensi gelap OS hanya berlaku saat pengguna belum secara eksplisit memilih light mode. Setelah mereka toggle, pilihan eksplisit mereka menang.
Mekanisme Toggle dengan JavaScript
Toggle yang diimplementasikan dengan baik melakukan tiga hal: mengubah tampilan saat ini secara langsung, menyimpan preferensi di localStorage, dan membaca preferensi yang tersimpan saat halaman dimuat sebelum paint pertama.
Membaca Preferensi saat Muat
Skrip ini harus berjalan di <head> — sebelum halaman dirender — untuk mencegah flash tema yang salah:
<head>
<script>
(function() {
const stored = localStorage.getItem('theme');
const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
const theme = stored ?? (prefersDark ? 'dark' : 'light');
document.documentElement.setAttribute('data-theme', theme);
})();
</script>
</head>
Ini segera mengatur data-theme pada <html> sebelum style apa pun diterapkan. Browser menghitung nilai custom property yang benar dari paint pertama — tanpa flash.
Fungsi Toggle
function toggleTheme() {
const current = document.documentElement.getAttribute('data-theme');
const next = current === 'dark' ? 'light' : 'dark';
document.documentElement.setAttribute('data-theme', next);
localStorage.setItem('theme', next);
}
// Hubungkan ke tombol
document.getElementById('theme-toggle').addEventListener('click', toggleTheme);
Menyinkronkan Status Tombol Toggle
Tombol toggle harus mencerminkan mode saat ini secara visual. Pendekatan sederhana menggunakan ikon:
<button id="theme-toggle" aria-label="Toggle dark mode">
<span class="icon-light">☀️</span>
<span class="icon-dark">🌙</span>
</button>
[data-theme="dark"] .icon-light { display: none; }
[data-theme="dark"] .icon-dark { display: inline; }
[data-theme="light"] .icon-light { display: inline; }
[data-theme="light"] .icon-dark { display: none; }
Karena visibilitas ikon dikendalikan oleh CSS variables yang terikat pada data-theme, status tombol diperbarui otomatis setiap kali atribut berubah — tanpa JavaScript tambahan.
Strategi Adaptasi Warna
Memilih warna dark mode tidak sesederhana membalikkan palet terang. Beberapa prinsip memandu pilihan warna gelap yang baik.
Kurangi Kontras, Bukan Hanya Balikkan
Teks putih murni pada latar hitam murni (#FFFFFF pada #000000) secara teknis adalah kontras maksimum — 21:1 — tetapi melelahkan secara kognitif untuk pembacaan panjang. Kurangi kedua ekstrem: gunakan putih keabu-abuan seperti #E8E8F0 untuk teks isi dan navy sangat gelap seperti #0F0F17 untuk latar halaman. Ini mempertahankan kontras yang memadai (masih di atas 15:1) sambil mengurangi kelelahan visual.
Gunakan Contrast Checker untuk memverifikasi bahwa setiap kombinasi teks/latar belakang dalam tema gelap Anda memenuhi minimal WCAG AA (4,5:1 untuk teks normal, 3:1 untuk teks besar).
Elevasi Berlapis dengan Permukaan Gelap
Dalam light mode, elevasi biasanya diekspresikan dengan drop shadow. Dalam dark mode, shadow menjadi tidak terlihat terhadap latar gelap. Spesifikasi Material Design 3 memperkenalkan pendekatan yang lebih efektif: permukaan yang lebih terang terasa lebih tinggi. Gunakan latar belakang yang sedikit lebih terang untuk komponen yang ditinggikan:
/* Skala elevasi dark mode */
--color-bg-base: #0F0F17; /* Latar halaman */
--color-bg-elevated: #1A1A2E; /* Kartu, sidebar */
--color-bg-overlay: #252540; /* Modal, dropdown */
--color-bg-tooltip: #2E2E4A; /* Tooltip */
#0F0F17 sebagai dasar, #1A1A2E untuk kartu, #252540 untuk modal — setiap langkah sekitar 8–10% lebih terang dalam istilah kecerahan HSL. Ini menciptakan hierarki visual yang jelas tanpa mengandalkan shadow.
Desaturasi Warna Dark Mode Sedikit
Warna yang sangat tersaturasi terlihat keras dan seperti neon pada latar gelap. Saat mengadaptasi warna brand untuk dark mode, kurangi saturasi 10–20% bersamaan dengan meningkatkan kecerahan. Alih-alih hijau sukses yang vivid #22C55E, lebih baik #4ADE80 — lebih terang dan sedikit kurang tersaturasi, yang terbaca sebagai sukses tanpa ketegangan mata.
Gambar dan Media
Gambar dengan latar putih terlihat janggal dalam dark mode. CSS dapat membantu:
/* Kurangi kekerasan gambar dalam dark mode */
[data-theme="dark"] img:not([src*=".svg"]) {
filter: brightness(0.9) contrast(1.05);
}
Untuk ikon SVG yang perlu beradaptasi, menggunakan currentColor sebagai nilai fill berarti mereka secara otomatis mengadopsi warna teks saat ini:
.icon { color: var(--color-text-secondary); }
<svg fill="currentColor" viewBox="0 0 24 24">...</svg>
Menguji Kedua Mode
Pengujian menyeluruh mencegah regresi dark mode masuk ke produksi.
Emulasi DevTools Browser
Chrome dan Firefox menawarkan emulasi dark mode di DevTools tanpa mengubah pengaturan OS. Di Chrome: buka DevTools, klik menu tiga titik, buka More Tools → Rendering, dan atur "Emulate CSS media feature prefers-color-scheme" ke "dark."
Pengujian Kontras Otomatis
Pemeriksaan manual rentan terhadap kesalahan. Integrasikan audit kontras otomatis ke dalam alur kerja pengembangan Anda. Contrast Checker memungkinkan Anda memverifikasi pasangan foreground/background dengan cepat terhadap semua level WCAG.
Daftar Periksa Kesalahan Umum
- Nilai hex yang dikodekan keras dalam CSS komponen alih-alih variabel — cari kode hex mentah dan ganti dengan variabel
- Ikon SVG dengan
fill="#000000"yang dikodekan keras — ubah menjadifill="currentColor" - Komponen pihak ketiga yang tidak menghormati
data-theme— bungkus dalam lapisan CSS yang dilingkupi - Properti
color-schemetidak diatur — tambahkancolor-scheme: light darkke:root
<meta name="color-scheme" content="light dark">
:root {
color-scheme: light dark;
}
Penambahan kecil ini membuat scrollbar asli, date picker, dan kontrol formulir yang dirender OS secara otomatis beralih ke varian gelap mereka.
Poin Utama
- Definisikan semua warna sebagai CSS custom properties pada
:rootdan timpa untuk dark mode menggunakan[data-theme="dark"]. Style komponen hanya merujuk variabel, membuat pergantian tema tanpa usaha setelah palet ditetapkan. - Gunakan
prefers-color-scheme: darksebagai default otomatis untuk pengguna yang menyetel OS ke tampilan gelap. Lapisi toggle JavaScript dengan persistensilocalStoragedi atasnya untuk pengguna yang ingin mengganti. - Jalankan skrip anti-flash di
<head>sebelum CSS dimuat untuk mencegah flash tema yang salah pada paint pertama. - Warna dark mode bukan warna terang yang dibalik — kurangi kontras ekstrem, gunakan latar belakang lebih terang untuk menyampaikan elevasi, dan desaturasi aksen brand sedikit untuk menghindari kekerasan neon.
- Verifikasi setiap pasangan teks/latar dengan Contrast Checker dan gunakan Shade Generator untuk menemukan shade yang tepat dari setiap warna brand untuk kedua tema.
- Tambahkan
color-scheme: light darkdan tag<meta>yang sesuai agar elemen UI browser asli (scrollbar, input) juga beralih secara otomatis.