Dark UI (dark mode) adalah versi halaman dengan latar gelap dan teks terang. Dark UI yang baik bukan halaman terang yang warnanya dibalik, tapi didesain ulang. Bayangin teras homestay Bu Sri jam sembilan malam, cuma ada satu lampu di atas. Lantainya abu tua, bukan hitam pekat. Meja yang lebih tinggi, lebih dekat ke lampu, kelihatan lebih terang dari lantai. Dan bayangan meja hampir gak kelihatan, karena lantainya sudah gelap. Tiga hal itu persis aturan dark UI: latar abu tua, yang "lebih tinggi" lebih terang, dan shadow gak lagi bekerja.
🧪 Tebakan cepat: Di versi terang, kartu kamar Bu Sri punya shadow
0 1px 3px rgba(0, 0, 0, 0.1). Kamu bikin versi gelap dengan latar#111827, dan shadow-nya dibiarkan. Shadow itu masih kelihatan? Jawabannya ada di bagian "Elevasi: permukaan lebih terang, bukan shadow".
Bukan dibalik, tapi didesain ulang
Ini peran tiap warna di halaman pesan Homestay Kabut, di versi terang dan versi gelap. Kontrasnya dihitung dengan rumus WCAG, terhadap permukaan tempat warna itu duduk:
| Peran | Terang | Gelap |
|---|---|---|
| Latar halaman | #ffffff |
#111827 |
Kartu (.kabut) |
#ffffff + garis + shadow |
#1f2937, tanpa shadow |
| Garis | #e2e8f0 |
#374151 |
| Teks utama | #1f2937 (14,68:1) |
#f1f5f9 (13,40:1) |
| Teks kedua | #475569 (7,58:1) |
#94a3b8 (5,72:1) |
| Hijau (tombol, malam terpilih) | #15803d, teks putih (5,02:1) |
#22c55e, teks #111827 (7,79:1) |
Kalau warna terang dipakai apa adanya di atas kartu gelap, teks kedua #475569 cuma 1,94:1 dan gak terbaca. Tiap warna harus dipilih ulang dan diukur ulang.
Latar: abu tua, bukan #000
Teks putih di atas #000000 punya kontras 21:1, angka tertinggi yang mungkin. Kedengarannya bagus, tapi terlalu kontras. Material Design (panduan desain dari Google) menyarankan #121212 sebagai permukaan dark theme, dengan alasan: abu tua mengurangi kelelahan mata, karena teks terang di atas abu tua kontrasnya lebih rendah daripada di atas hitam. Abu tua juga menyisakan ruang ke bawah, jadi permukaan yang lebih tinggi bisa dibuat lebih terang.
Halaman Bu Sri memakai #111827. Teks #f1f5f9 di atasnya 16,19:1, masih jauh di atas syarat 4,5:1. Satu-satunya argumen untuk hitam pekat: di layar OLED, piksel hitam benar-benar mati dan menghemat baterai. Karena itu sebagian aplikasi menawarkannya sebagai pilihan tambahan, bukan bawaan.
Elevasi: permukaan lebih terang, bukan shadow
Di versi terang, kartu terpisah dari latar karena shadow-nya sedikit menggelapkan latar putih. Shadow rgba(0, 0, 0, 0.1) di titik paling gelapnya mengubah putih jadi #e6e6e6, beda 1,25:1, cukup untuk terlihat.
Di versi gelap, shadow yang sama mengubah #111827 jadi #0f1623, bedanya cuma 1,02:1. Di atas #000 bedanya 1,00:1: gak ada apa-apa. Jadi jawaban tebakannya: hampir gak kelihatan. Menggelapkan sesuatu yang sudah gelap gak menghasilkan beda. Itu jawaban tebakannya.
Gantinya, elemen yang lebih "tinggi" diberi permukaan yang lebih terang: latar #111827, kartu #1f2937 (1,21:1 terhadap latar), dan menu atau dialog di atas kartu bisa lebih terang lagi, misalnya #374151. Material Design menyebut ini elevation overlay: makin tinggi permukaannya, makin terang.
Hijau di atas gelap: ukur ulang
Hijau #15803d dipakai untuk tombol pesan dan tombol malam yang terpilih. Di versi terang, yang menandai "2 malam terpilih" adalah isian hijaunya, dan WCAG 1.4.11 (kontras non-teks) meminta penanda keadaan seperti itu minimal 3:1 terhadap warna di sebelahnya. Di kartu putih: 5,02:1, lolos.
Di kartu gelap #1f2937, hijau yang sama cuma 2,93:1, gagal. Tombol terpilih dan tidak terpilih jadi susah dibedakan. Hijau yang lebih terang, #22c55e, punya 6,44:1 terhadap kartu. Tapi teks putih di atas #22c55e cuma 2,28:1, jadi teks tombolnya ikut diganti ke #111827 (7,79:1). Aksen di dark mode biasanya lebih terang dan sedikit kurang pekat daripada di versi terang, dan teks di atasnya jadi gelap.
prefers-color-scheme: ikut setelan OS
Pengguna memilih mode terang atau gelap di setelan HP atau laptopnya. CSS membaca pilihan itu lewat media query prefers-color-scheme. Simpan semua warna di CSS variable, lalu ganti nilainya di satu blok:
:root {
color-scheme: light dark;
--bg: #ffffff; --surface: #ffffff; --line: #e2e8f0;
--text: #1f2937; --muted: #475569;
--accent: #15803d; --on-accent: #ffffff;
--shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
}
@media (prefers-color-scheme: dark) {
:root {
--bg: #111827; --surface: #1f2937; --line: #374151;
--text: #f1f5f9; --muted: #94a3b8;
--accent: #22c55e; --on-accent: #111827;
--shadow: none; /* elevasi lewat --surface yang lebih terang */
}
}
body { background: var(--bg); color: var(--text); }
.kabut { background: var(--surface); border: 1px solid var(--line); box-shadow: var(--shadow); }
.note { color: var(--muted); }
.book { background: var(--accent); color: var(--on-accent); }
@media (prefers-color-scheme: dark)berlaku saat OS pengguna di mode gelap. Isinya cuma nilai variable baru; aturan.kabutdan.bookgak ditulis dua kali.color-scheme: light darkmemberi tahu browser bahwa halaman ini siap untuk dua mode, jadi input tanggal, scrollbar, dan kontrol bawaan lain ikut gelap. Tanpa ini, input tanggal tetap putih menyilaukan di halaman gelap.--shadow: nonedi mode gelap: shadow-nya gak terlihat, jadi dibuang saja.
⚠️ Jebakan yang sering ketemu
- Hitam pekat dan putih murni. 21:1 terlalu keras. Pakai abu tua (
#111827,#121212) dan teks off-white (#f1f5f9). - Membawa shadow ke mode gelap. Bedanya 1,02:1. Pakai permukaan yang lebih terang untuk elevasi.
- Aksen gak diukur ulang.
#15803dlolos di kartu putih (5,02:1) tapi gagal di kartu gelap (2,93:1). - Membalik warna dengan
filter: invert(1). Foto ikut terbalik, hijau#15803djadi merah muda#ea7fc2, dan hierarki terang gelapnya kacau.
TL;DR: Dark UI didesain ulang, bukan dibalik. Jangan pakai #000000 sebagai latar: putih di atasnya 21:1, terlalu kontras, dan Material Design menyarankan abu tua (#121212) karena teks terang di atas abu tua lebih ringan di mata; halaman Bu Sri memakai #111827. Shadow gak terlihat di latar gelap (bedanya cuma 1,02:1), jadi elevasi ditunjukkan dengan permukaan yang lebih terang: latar #111827, kartu #1f2937. Ukur ulang tiap warna: teks kedua jadi #94a3b8 (5,72:1), hijau jadi #22c55e (6,44:1 terhadap kartu, minimal 3:1 menurut WCAG 1.4.11) dengan teks #111827 di atasnya. Simpan warna di CSS variable, ganti nilainya di @media (prefers-color-scheme: dark), dan tambahkan color-scheme: light dark supaya kontrol bawaan ikut gelap.