Media query prefers-color-scheme adalah titik sambung antara sistem desain dan preferensi pengguna: browser membaca skema warna yang dipilih pada tingkat sistem operasi, lalu media query menyaring kapan blok gaya tertentu berlaku. Chapter Dark Mode memakai query ini sebagai penimpa token otomatis; chapter ini membahasnya sebagai topik tersendiri — cara menulisnya, bagaimana nilai default bekerja saat tidak ada preferensi, cara mengujinya lewat emulasi DevTools, dan cara kombinasinya dengan override manual data-tema yang tidak boleh kalah oleh preferensi sistem. Pola media query dasarnya sendiri sudah kita pelajari pada Chapter Media Queries .

Query ini punya dua nilai utama: light dan dark. Blok dark berlaku ketika pengguna memilih skema gelap pada sistem operasinya:

:root {
  --latar: rgb(255, 255, 255);
  --teks: rgb(15, 23, 42);
  --aksen: rgb(29, 78, 216);
}

@media (prefers-color-scheme: dark) {
  :root {
    --latar: rgb(17, 24, 39);
    --teks: rgb(229, 231, 235);
    --aksen: rgb(147, 197, 253);
  }
}

/* Override manual — menang melalui kedekatan inheritance */
[data-tema="gelap"] {
  --latar: rgb(17, 24, 39);
  --teks: rgb(229, 231, 235);
  --aksen: rgb(147, 197, 253);
}

[data-tema="terang"] {
  --latar: rgb(255, 255, 255);
  --teks: rgb(15, 23, 42);
  --aksen: rgb(29, 78, 216);
}

.panel {
  background-color: var(--latar);
  color: var(--teks);
  border: 1px solid rgb(203, 213, 225);
  border-radius: 12px;
  padding: 16px;
}

Mari kita telaah mekanismenya:

  1. :root sebagai tema default: nilai terang ditulis di luar media query, sehingga berlaku untuk semua kondisi — termasuk ketika pengguna tidak pernah menyetel preferensi. Nilai no-preference tidak perlu ditangani blok terpisah; default-nya cukup.
  2. Blok dark hanya menimpa token: media query menyaring kapan penimpaan berlaku, tetapi isinya tetap penimpaan variabel — komponen tidak menulis ulang apa pun.
  3. Override manual menang melalui kedekatan, bukan specificity: media query menulis pada :root, sedangkan [data-tema] menulis pada elemen panel. Custom properties diwarisi dari leluhur terdekat, sehingga nilai milik panel selalu lebih dekat daripada nilai milik :root — tidak ada benturan specificity yang perlu dimenangkan.

Dua batas perilaku juga patut dipahami sejak awal. Pertama, query ini bersifat satu arah: halaman dapat menanggapi preferensi sistem, tetapi tidak dapat mengubahnya — halaman yang ingin memberi pengguna pilihan sendiri membutuhkan sakelar manual seperti pada Chapter berikutnya. Kedua, kecocokan terjadi pada tingkat yang tidak terlihat oleh CSS: browser hanya menanyakan sistem operasi, sehingga tidak ada pseudo-class atau fungsi yang bisa membaca nilai terpilihnya; blok dark berlaku atau tidak, tanpa tingkat di antaranya. Bila sebuah elemen harus tetap terang di tengah halaman gelap, kuncinya secara eksplisit dengan blok [data-tema="terang"] seperti di atas, bukan dengan mengandalkan ketiadaan query.

Menguji Tanpa Mengubah Sistem Operasi #

Preferensi skema warna milik pengguna, bukan milik halaman, sehingga satu-satunya cara mengujinya adalah menyimulasikannya. DevTools menyediakan jalur resminya: buka panel Rendering melalui menu More tools, cari bagian Emulate CSS media feature prefers-color-scheme, lalu pilih dark atau light. Emulasi ini berlaku hanya pada tab tersebut, sehingga halaman dapat dibandingkan dua-duanya dalam satu sesi. Untuk pengujian otomatis perlu diingat: browser headless memakai mode terang secara default, sehingga harness Course ini selalu memverifikasi nilai terang pada demo.

Demo: Tiga Panel dengan Sumber Nilai Berbeda #

Demo chapter ini menampilkan tiga panel dari aturan .panel yang sama: panel default yang membaca :root, panel data-tema="gelap", dan panel data-tema="terang".

Hasil di Browser:

text
Pada browser headless ber-mode terang, panel default tampil
berlatar rgb(255, 255, 255) dengan teks rgb(15, 23, 42).
Panel data-tema="gelap" tampil berlatar rgb(17, 24, 39) dengan
teks rgb(229, 231, 235) dan aksen rgb(147, 197, 253).
Panel data-tema="terang" menampilkan nilai terang yang sama
dengan panel default, kini dikunci secara eksplisit.

Kelima nilai tersebut diverifikasi otomatis melalui penanda data-expected. Emulasikan skema gelap pada DevTools dan perhatikan: hanya panel default yang berubah, karena dua panel lainnya terkunci oleh atributnya masing-masing. Perilaku inilah yang dijadikan sakelar manual pengguna pada Chapter Theme Switching Overview .

Berkas Sumber

Berkas pendukung halaman ini dapat diunduh dan dijalankan langsung sesuai penjelasan di atas.

contoh-media-scheme.css

Unduh berkas
css
:root {
  --latar: rgb(255, 255, 255);
  --teks: rgb(15, 23, 42);
  --aksen: rgb(29, 78, 216);
}

@media (prefers-color-scheme: dark) {
  :root {
    --latar: rgb(17, 24, 39);
    --teks: rgb(229, 231, 235);
    --aksen: rgb(147, 197, 253);
  }
}

/* Override manual — menang melalui kedekatan inheritance */
[data-tema="gelap"] {
  --latar: rgb(17, 24, 39);
  --teks: rgb(229, 231, 235);
  --aksen: rgb(147, 197, 253);
}

[data-tema="terang"] {
  --latar: rgb(255, 255, 255);
  --teks: rgb(15, 23, 42);
  --aksen: rgb(29, 78, 216);
}

.panel {
  background-color: var(--latar);
  color: var(--teks);
  border: 1px solid rgb(203, 213, 225);
  border-radius: 12px;
  padding: 16px;
}