Dark mode sudah menjadi fitur yang hampir wajib ada di website modern. Selain memberikan pengalaman membaca yang lebih nyaman di malam hari, dark mode juga bisa menghemat daya baterai pada layar OLED. Di artikel ini kita akan implementasi dark mode di blog Jekyll menggunakan CSS Custom Properties (CSS Variables) dan JavaScript minimal.
Pendekatan yang Akan Digunakan
Ada dua pendekatan utama untuk dark mode:
- Ikuti preferensi sistem — otomatis gelap jika OS user menggunakan dark mode, lewat
prefers-color-scheme - Toggle manual — user bisa klik tombol untuk beralih antara light/dark
Kita akan implementasi keduanya: secara default mengikuti preferensi sistem, tapi user tetap bisa override lewat tombol toggle.
Langkah 1: Definisikan CSS Variables
Buka file CSS utama kamu (misalnya assets/css/main.css atau assets/css/theme.css) dan tambahkan CSS variables untuk kedua mode:
/* Light mode (default) */
:root {
--bg-color: #ffffff;
--bg-secondary: #f8f9fa;
--text-color: #212529;
--text-muted: #6c757d;
--border-color: #dee2e6;
--link-color: #0d6efd;
--link-hover: #0a58ca;
--card-bg: #ffffff;
--card-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
--code-bg: #f1f3f5;
--code-color: #e83e8c;
--heading-color: #1a1a2e;
}
/* Dark mode */
[data-theme="dark"] {
--bg-color: #1a1a2e;
--bg-secondary: #16213e;
--text-color: #e0e0e0;
--text-muted: #9e9e9e;
--border-color: #2d3748;
--link-color: #63b3ed;
--link-hover: #90cdf4;
--card-bg: #16213e;
--card-shadow: 0 2px 8px rgba(0, 0, 0, 0.4);
--code-bg: #2d3748;
--code-color: #f687b3;
--heading-color: #e2e8f0;
}
/* Auto dark mode berdasarkan preferensi sistem */
@media (prefers-color-scheme: dark) {
:root:not([data-theme="light"]) {
--bg-color: #1a1a2e;
--bg-secondary: #16213e;
--text-color: #e0e0e0;
--text-muted: #9e9e9e;
--border-color: #2d3748;
--link-color: #63b3ed;
--link-hover: #90cdf4;
--card-bg: #16213e;
--card-shadow: 0 2px 8px rgba(0, 0, 0, 0.4);
--code-bg: #2d3748;
--code-color: #f687b3;
--heading-color: #e2e8f0;
}
}
Langkah 2: Terapkan Variables ke Elemen CSS
Sekarang gunakan variables tersebut di seluruh CSS kamu:
body {
background-color: var(--bg-color);
color: var(--text-color);
transition: background-color 0.3s ease, color 0.3s ease;
}
a {
color: var(--link-color);
}
a:hover {
color: var(--link-hover);
}
h1, h2, h3, h4, h5, h6 {
color: var(--heading-color);
}
.card, .post-card {
background-color: var(--card-bg);
border: 1px solid var(--border-color);
box-shadow: var(--card-shadow);
}
code {
background-color: var(--code-bg);
color: var(--code-color);
}
pre {
background-color: var(--code-bg);
border: 1px solid var(--border-color);
}
.text-muted {
color: var(--text-muted) !important;
}
Langkah 3: Tambahkan Tombol Toggle
Di layout header (_includes/menu-header.html atau tempat yang sesuai), tambahkan tombol toggle:
<button id="theme-toggle" aria-label="Toggle dark mode" title="Toggle dark mode">
<span id="theme-icon">🌙</span>
</button>
CSS untuk tombolnya:
#theme-toggle {
background: none;
border: 1px solid var(--border-color);
border-radius: 50%;
width: 36px;
height: 36px;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
font-size: 16px;
transition: border-color 0.3s, transform 0.2s;
color: var(--text-color);
}
#theme-toggle:hover {
transform: scale(1.1);
border-color: var(--link-color);
}
Langkah 4: JavaScript untuk Toggle dan Persistensi
Buat file assets/js/dark-mode.js atau tambahkan script berikut ke _includes/dark-mode.html:
<script>
(function() {
// Ambil preferensi tersimpan atau deteksi dari sistem
function getPreferredTheme() {
const saved = localStorage.getItem('theme');
if (saved) return saved;
return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
}
// Terapkan tema
function applyTheme(theme) {
document.documentElement.setAttribute('data-theme', theme);
localStorage.setItem('theme', theme);
const icon = document.getElementById('theme-icon');
if (icon) {
icon.textContent = theme === 'dark' ? '☀️' : '🌙';
}
}
// Terapkan tema secepat mungkin untuk menghindari flash
applyTheme(getPreferredTheme());
// Setup toggle button setelah DOM siap
document.addEventListener('DOMContentLoaded', function() {
const toggle = document.getElementById('theme-toggle');
if (toggle) {
toggle.addEventListener('click', function() {
const current = document.documentElement.getAttribute('data-theme');
applyTheme(current === 'dark' ? 'light' : 'dark');
});
}
// Dengarkan perubahan preferensi sistem
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', function(e) {
// Hanya update jika user belum punya preferensi tersimpan
if (!localStorage.getItem('theme')) {
applyTheme(e.matches ? 'dark' : 'light');
}
});
});
})();
</script>
Langkah 5: Cegah Flash of Unstyled Content (FOUC)
Masalah umum dark mode adalah FOUC — halaman muncul sebentar dengan tema terang sebelum berubah ke gelap. Untuk mencegahnya, pastikan script theme diterapkan sebelum elemen body dirender.
Tambahkan script ini langsung di dalam <head>, sebelum tag CSS apapun:
<head>
<!-- Anti-FOUC: terapkan tema sebelum render -->
<script>
const theme = localStorage.getItem('theme') ||
(window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light');
document.documentElement.setAttribute('data-theme', theme);
</script>
<!-- CSS dan tag lainnya di bawah ini -->
<link rel="stylesheet" href="/assets/css/main.css">
...
</head>
Dark Mode untuk Gambar
Agar gambar tidak terlalu menyilaukan di dark mode, tambahkan CSS ini:
[data-theme="dark"] img:not([src*=".svg"]) {
filter: brightness(0.85) contrast(1.05);
}
[data-theme="dark"] img:hover {
filter: brightness(1);
transition: filter 0.3s ease;
}
Kesimpulan
Implementasi dark mode di Jekyll menggunakan CSS Variables + JavaScript minimal sangat efektif. Pendekatan ini:
- Ringan — tidak butuh framework atau library tambahan
- Persisten — preferensi disimpan di localStorage
- Respek preferensi sistem — mengikuti
prefers-color-schemesecara default - Bebas FOUC — dengan script anti-flash di
<head>
Cukup definisikan warna di CSS Variables, terapkan ke seluruh elemen, dan tambahkan satu script JavaScript — dark mode siap digunakan.
Kiki/🎮🍉⌨️🍩💻