Episode ini membahas custom properties dan tema berbasis variabel: mendefinisikan dan membaca nilai dengan var(), cakupan dan pewarisan variabel, fallback, serta pembuatan tema terang dan gelap yang bertukar lewat class atau preferensi sistem.

Menulis warna dan spacing yang sama berulang kali membuat stylesheet sulit dirawat — ganti satu merek warna berarti mengubah puluhan nilai. Custom properties menjawabnya: kalian menyimpan nilai sekali, lalu merujuknya di mana saja. Ubah definisinya, seluruh antarmuka ikut berubah. Berbeda dari variabel preprocessor seperti Sass yang diselesaikan saat build, custom properties hidup di runtime. Nilainya bisa dibaca dan diubah oleh JavaScript, diwariskan ke anak elemen, dan dibalik dengan cepat untuk tema gelap. Mengapa penting? Custom properties adalah fondasi design system modern. Tema, dark mode, dan penyetelan runtime semuanya dibangun di atas satu mekanisme yang sederhana namun sangat kuat.
Custom property dideklarasikan dengan awalan -- dan dibaca lewat fungsi var():
:root {
--warna-utama: #2563eb;
--warna-teks: #0f172a;
--jarak-besar: 24px;
--radius-kartu: 12px;
}
.kartu {
background-color: var(--warna-utama);
border-radius: var(--radius-kartu);
padding: var(--jarak-besar);
}Menempatkan definisi di :root — selector untuk elemen root — membuat variabel tersedia di seluruh dokumen. Nilai bisa berupa warna, ukuran, angka, bahkan daftar panjang, dan diterima di semua properti yang cocok.
.konten {
width: calc(100% - var(--jarak-samping));
gap: var(--jarak, 16px);
}Custom properties bisa dipakai di dalam fungsi lain seperti calc(). Argumen kedua var() adalah fallback — nilai yang dipakai bila variabel belum terdefinisi. Ini menjaga desain tetap berfungsi meski variabel hilang.
Variabel diwariskan ke elemen turunan seperti properti lainnya. Mendefinisikan ulang pada elemen tertentu menimpa nilai untuk subtree-nya:
:root {
--warna-aksi: #2563eb;
}
.berbahaya {
--warna-aksi: #dc2626;
}
.tombol {
background-color: var(--warna-aksi);
color: white;
padding: 8px 16px;
}Tombol di dalam .berbahaya otomatis berwarna merah, sementara tombol lain tetap biru. Pola ini memungkinkan komponen yang sama tampil berbeda sesuai konteksnya tanpa mengubah HTML — salah satu kekuatan utama custom properties.
Tema paling sederhana adalah mendefinisikan ulang variabel pada kelas tertentu:
:root,
[data-theme="terang"] {
--warna-latar: #ffffff;
--warna-permukaan: #f1f5f9;
--warna-teks: #0f172a;
}
[data-theme="gelap"] {
--warna-latar: #0f172a;
--warna-permukaan: #1e293b;
--warna-teks: #f8fafc;
}
body {
background-color: var(--warna-latar);
color: var(--warna-teks);
}
.surface {
background-color: var(--warna-permukaan);
}Mengganti atribut data-theme pada elemen root langsung mengganti seluruh palet, karena semua komponen merujuk variabel yang sama. Tidak ada satu pun aturan yang perlu ditulis ulang untuk tema baru.
Tema juga bisa mengikuti preferensi sistem lewat prefers-color-scheme:
:root {
--warna-latar: #ffffff;
--warna-teks: #0f172a;
--warna-utama: #2563eb;
}
@media (prefers-color-scheme: dark) {
:root {
--warna-latar: #0f172a;
--warna-teks: #f8fafc;
--warna-utama: #60a5fa;
}
}Aturan ini menimpa variabel saat sistem dalam mode gelap. Untuk memberikan kontrol pengguna, tambahkan atribut data-theme yang mengalahkan preferensi sistem:
:root[data-theme="gelap"] {
--warna-latar: #0f172a;
--warna-teks: #f8fafc;
}
:root[data-theme="terang"] {
--warna-latar: #ffffff;
--warna-teks: #0f172a;
}Karena variabel hidup di runtime, JavaScript bisa menukar tema tanpa reload:
<!DOCTYPE html>
<html lang="id" data-theme="terang">
<head>
<meta charset="UTF-8">
<title>Tema</title>
<link rel="stylesheet" href="css/style.css">
</head>
<body>
<button id="gantiTema">Ganti Tema</button>
</body>
</html>:root { --warna-latar: #ffffff; --warna-teks: #0f172a; --warna-permukaan: #f1f5f9; transition: background-color 0.3s ease, color 0.3s ease; }
:root[data-theme="gelap"] { --warna-latar: #0f172a; --warna-teks: #f8fafc; --warna-permukaan: #1e293b; }
body { background-color: var(--warna-latar); color: var(--warna-teks); font-family: system-ui, sans-serif; }
button { padding: 10px 18px; border: none; border-radius: 8px; background-color: var(--warna-permukaan); color: var(--warna-teks); }const html = document.documentElement;
const tombol = document.getElementById("gantiTema");
tombol.addEventListener("click", () => {
const kini = html.getAttribute("data-theme");
const berikut = kini === "gelap" ? "terang" : "gelap";
html.setAttribute("data-theme", berikut);
});Jalankan npx serve . lalu klik tombol Ganti Tema. Atribut data-theme berpindah, variabel berubah, dan seluruh halaman berganti palet dalam sekejap tanpa memuat ulang.
Custom property yang didefinisikan di :root bisa ditimpa oleh nilai yang lebih dekat atau salah ketik nama. Pastikan nama konsisten dan tidak ada definisi ulang yang tak disengaja.
Fallback var(--x, nilai) hanya aktif bila variabel tidak terdefinisi, bukan saat nilainya kosong. Set nilai variabel secara eksplisit bila perlu perilaku default.
Mendefinisikan ulang ratusan variabel untuk setiap tema membengkak. Simpan palet dasar di :root, lalu timpa hanya yang berubah pada tiap tema.
Inti yang harus dibawa pulang:
-- dan dibaca via var().:root menjadikan variabel global; nilai bisa ditimpa per subtree.var() mendukung fallback untuk menjaga desain tetap berfungsi.prefers-color-scheme memungkinkan dark mode otomatis.calc, min, max, dan clamp untuk menghitung ukuran yang menyesuaikan diri.