Implementasi Dark Mode dengan CSS variable dan Javascript

Bagian Dari Seri Implementasi Dark Mode

Ditulis

Semenjak seluruh sistem operasi desktop dan mobile memiliki dark mode, banyak aplikasi mengikuti tren tersebut dan menyediakan dark mode pada antar muka mereka.

Tidak hanya pada aplikasi native, banyak website juga mengimplementasikan dark mode khususnya blog dan portal berita untuk membantu pengguna membaca secara nyaman dalam kondisi rendah cahaya.

Bahkan sudah ada CSS media query Export Square untuk mendeteksi tema dan mengaktifkan styles berdasarkan pengaturan tema yang pengguna setel.

@media (prefers-color-scheme: light) {
/* Light theme styles */
}
@media (prefers-color-scheme: dark) {
/* Dark theme styles */
}

Tapi untuk sekarang kita akan mengimplementasikan dark mode pada website menggunakan CSS variable Export Square , data-* attribute Export Square dan sedikit javascript untuk mengkontrol tema-nya.

Kenapa tidak menggunakan media query? Karena jika kita menggunakan metode tersebut, kita harus menulis seluruh perubahan di dalam blok media query seperti berikut:

body {
background: white;
}
@media (prefers-color-scheme: dark) {
body {
background: black;
}
}

Atau, kita harus menulis dua CSS berbeda untuk tiap tema dasar dan dark mode seperti ini:

<link
rel="stylesheet"
href="/css/dark.css"
media="(prefers-color-scheme: dark)"
/>
<link
rel="stylesheet"
href="/css/light.css"
media="(prefers-color-scheme: no-preference), (prefers-color-scheme: light)"
/>

Saya merasa kedua metode tersebut kurang praktis. Dengan menggunakan CSS variable, kita hanya perlu mendefinisikan variable untuk tema dasar dan dark mode lalu merubahnya berda sarkan data attribute yang kita setel di tag <html>.

Ayo kita buat file HTML untuk konten dasar dan tombol sebagai toggle

index.html
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>Dark Mode Using CSS Variable</title>
<link rel="stylesheet" href="styles.css" />
</head>
<body>
<main id="main-wrapper">
<article class="container">
<div class="image-wrapper">
<img src="images/hero.jpg" alt="Hero Image" />
</div>
<section class="container">
<div class="content-wrapper">
<h1 class="title">Welcome to the Dark Side</h1>
<p class="subtitle">
Dark Mode using CSS variables and control it using javascript.
</p>
<button class="toggle">Toggle Dark Mode</button>
</div>
</section>
</article>
</main>
</body>
</html>

Sekarang, kita deklarasikan CSS variable kita didalam :root pseudo-class untuk tema dasar dan kita tambah beberapa styling dasar pada HTML kita.

styles.css
:root {
--background-color: #fff;
--title-color: #151515;
--subtitle-color: #353535;
--image-brightness: 100%;
}
body {
background: var(--background-color);
}
#main-wrapper {
width: 70%;
margin: 0 auto;
display: flex;
height: 100vh;
}
#main-wrapper .container {
align-self: center;
display: flex;
}
#main-wrapper .container .content-wrapper {
padding-left: 60px;
}
#main-wrapper .container .content-wrapper .title {
font-family: "Georgia";
font-weight: 900;
font-size: 62px;
color: var(--title-color);
}
#main-wrapper .container .content-wrapper .subtitle {
font-family: "Arial";
font-size: 18px;
letter-spacing: 0.025em;
line-height: 24px;
color: var(--subtitle-color);
}
#main-wrapper .container .content-wrapper .toggle {
padding: 8px 24px;
font-size: 16px;
border-radius: 8px;
background: var(--subtitle-color);
color: var(--background-color);
}
#main-wrapper .container .image-wrapper img {
width: 400px;
height: 400px;
object-fit: cover;
filter: brightness(var(--image-brightness));
}
Hasil tampilan HTML dan CSS
Hasil dari tampilan HTML dan CSS di atas

Seperti yang bisa kita lihat, kita memasang tiap warna menggunakan variable karena kita akan menimpa tiap nilai variable-nya saat kita mengaktifkan dark mode. Sekarang, kita deklarasikan variable untuk dark mode didalam data attribute [data-theme=”dark”].

styles.css
:root {
--background-color: #fff;
--title-color: #151515;
--subtitle-color: #353535;
--image-brightness: 100%;
}
[data-theme="dark"] {
--background-color: #00030f;
--title-color: #fff;
--subtitle-color: #ffffffdd;
--image-brightness: 60%;
}
/* ... Kode selanjutnya ... */

Untuk tes variable-nya, cobalah hapus atau komen :root dan ganti nama [data-theme=”dark”] menjadi :root untuk sementara.

styles.css
/* Hapus dulu untuk tes variable dibawah */
:root {
--background-color: #fff;
--title-color: #151515;
--subtitle-color: #353535;
--image-brightness: 100%;
}
:root {
--background-color: #00030f;
--title-color: #fff;
--subtitle-color: #ffffffdd;
--image-brightness: 60%;
}
Hasil tampilan HTML dan CSS
Hasil dari tampilan HTML dan CSS di atas

Jika sudah puas dengan warna yang kalian pilih, ubah kembali :root dan [data-theme=”dark”] seperti sebelumnya dan ayo kita ubah variable-nya secara dinamis menggunakan javascript.

index.html
<!-- ... Kode sebelumnya ... -->
<script>
function toggleTheme() {
/* Jika document memiliki atribut data-theme dengan nilai dark */
if (document.documentElement.getAttribute("data-theme") === "dark") {
/* Setel atribut menjadi light */
document.documentElement.setAttribute("data-theme", "light");
} else {
/* Jika tidak, setel ke dark */
document.documentElement.setAttribute("data-theme", "dark");
}
}
</script>
</body>
</html>

Dan pasang fungsi diatas ke event onclick tombol yang sudah kita buat sebelumnya.

<button class="toggle" onclick="toggleTheme()">Toggle Dark Mode</button>
Hasil toggle dark mode dengan kode di atas

Hore! Kita baru saja implementasi dark mode pada website! Tapi, perubahan temanya sangat tiba-tiba, bagaimana caranya jika ingin temanya berubah secara smooth?

Tak usah khawatir, ayo kita tambahkan properti transition ke setiap selector yang berubah ketika kita merubah tema, jadi perubahannya tidak akan tiba-tiba. Kita juga akan definisikan durasi transition di variable agar mudah untuk kita ubah.

styles.css
:root {
/* ... Kode sebelumnya ... */
--transition-duration: 0.5s; /* Durasi transisi */
}
body {
/* ... Kode sebelumnya ... */
transition: background var(--transition-duration) ease-in-out;
}
#main-wrapper .container .content-wrapper .title {
/* ... Kode sebelumnya ... */
transition: color var(--transition-duration) ease-in-out;
}
#main-wrapper .container .content-wrapper .subtitle {
/* ... Kode sebelumnya ... */
transition: color var(--transition-duration) ease-in-out;
}
#main-wrapper .container .content-wrapper .toggle {
/* ... Kode sebelumnya ... */
transition: all var(--transition-duration) ease-in-out;
}
#main-wrapper .container .image-wrapper img {
/* ... Kode sebelumnya ... */
transition: filter var(--transition-duration) ease-in-out;
}
Hasil toggle dark mode dengan kode di atas

Website dengan dark mode kita sudah selesai, dan sekarang perubahan temanya-pun berubah dengan smooth.

Di tulisan selanjutnya, saya akan menjelaskan bagaimana untuk memasang tema secara otomatis berdasarkan tema sistem operasi yang pengguna gunakan. Juga, bagaimana cara menyimpan pengaturan tema agar saat pengguna me-refresh website kita, temanya tidak akan kembali ke pengaturan awal.