Dark mode ni feature inayoongeza UX kwa kupunguza mwangaza, kuboresha kusoma usiku, na kuokoa battery kwenye vifaa za OLED. Katika makala hii utajifunza jinsi ya kutengeneza dark mode toggle yenye CSS variables, prefers-color-scheme detection, kuhifadhi chaguo la mtumiaji (localStorage), na kuhakikisha accessibility & smooth transitions. Code ni moja kwa moja kutumia kwenye blog au system yako ya PHP/HTML.

πŸ”– SEO Title & Meta
<title>Jinsi ya Kutengeneza Dark Mode Toggle kwa Website | Faulink Tutorials</title>
<meta name="description" content="Jifunze jinsi ya kutengeneza Dark Mode Toggle kwa website yako: CSS variables, prefers-color-scheme, localStorage, accessibility na code tayari kupaste.">
<meta name="keywords" content="Dark Mode, Dark Theme, CSS Variables, prefers-color-scheme, JavaScript, Faulink, web design">

✨ Ujenzi wa Approach (Quick overview)

Tumia CSS variables (custom properties) kufanya theme switching rahisi.

Toa default kulingana na prefers-color-scheme ya browser.

Ongeza toggle button (accessible) ambayo inabadilisha data-theme kwenye <html> au body.

Hifadhi chaguo la mtumiaji kwa localStorage ili kubaki persistent.

Ongeza transition nzuri kwa smooth change.

βœ… Full Code β€” Copy & paste
<!-- dark-mode-toggle.html -->
<!doctype html>
<html lang="sw" data-theme="">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width,initial-scale=1" />
<title>Dark Mode Toggle β€” Faulink Example</title>
<meta name="description" content="Mfano wa Dark Mode Toggle: CSS variables, prefers-color-scheme, localStorage, accessibility" />
<style>
/* 1. Define CSS variables for both themes */
:root {
--bg: #ffffff;
--text: #111827;
--muted: #6b7280;
--card: #f8fafc;
--accent: #0d6efd;
}

html[data-theme="dark"] {
--bg: #0b1220;
--text: #e6eef8;
--muted: #9aa6b2;
--card: #0f1724;
--accent: #5bb0ff;
}

/* 2. Respect system preference as a fallback */
@media (prefers-color-scheme: dark) {
:root:not([data-theme]) {
--bg: #0b1220;
--text: #e6eef8;
--muted: #9aa6b2;
--card: #0f1724;
--accent: #5bb0ff;
}
}

/* 3. Base styles */
* { box-sizing: border-box; }
body {
margin: 0;
font-family: Inter, system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial;
background: var(--bg);
color: var(--text);
line-height: 1.6;
transition: background-color 300ms ease, color 300ms ease;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}

.container {
max-width: 980px;
margin: 40px auto;
padding: 20px;
}

header {
display: flex;
justify-content: space-between;
align-items: center;
gap: 12px;
margin-bottom: 24px;
}

.card {
background: var(--card);
padding: 18px;
border-radius: 10px;
box-shadow: 0 6px 18px rgba(2,6,23,0.08);
transition: background 300ms ease, box-shadow 300ms ease;
}

/* Toggle button styles (accessible) */
.toggle {
display: inline-flex;
align-items: center;
gap: 8px;
background: transparent;
border: 1px solid rgba(0,0,0,0.08);
padding: 6px 10px;
border-radius: 999px;
cursor: pointer;
color: var(--text);
transition: background-color 200ms ease, border-color 200ms ease;
}

.toggle:focus {
outline: 3px solid rgba(13,110,253,0.18);
outline-offset: 2px;
}

.toggle .icon {
width: 18px;
height: 18px;
display: inline-block;
}

small { color: var(--muted); }

/* minor responsive */
@media (max-width: 520px) {
.container { padding: 12px; margin: 20px; }
}
</style>
</head>
<body>
<div class="container">
<header>
<h1>Jinsi ya Kutengeneza Dark Mode Toggle</h1>

<!-- Accessible toggle: button with aria-pressed -->
<button id="theme-toggle" class="toggle" aria-pressed="false" aria-label="Toggle dark mode">
<span class="icon" id="toggle-icon" aria-hidden="true">πŸŒ™</span>
<span id="toggle-text">Dark</span>
</button>
</header>

<main class="card" role="main">
<p>Hii ni demo ya <strong>dark mode</strong>. Bonyeza <em>Dark</em> ili kubadili kati ya light na dark themes. Chaguo lako kitahifadhiwa kwenye kivinjari.</p>

<h3>Features</h3>
<ul>
<li>CSS variables for easy theming</li>
<li>Respects <code>prefers-color-scheme</code></li>
<li>Panic-free transitions</li>
<li>Accessible toggle (keyboard + screen readers)</li>
</ul>

<p><small>Tip: unaweza ku-extend variables kwa border, shadows, link colors, n.k.</small></p>
</main>
</div>

<script>
(function () {
const root = document.documentElement;
const toggle = document.getElementById('theme-toggle');
const toggleIcon = document.getElementById('toggle-icon');
const toggleText = document.getElementById('toggle-text');

// 1) Get saved preference from localStorage
const storedTheme = localStorage.getItem('theme'); // "light" | "dark" | null

// 2) If user previously saved, apply it. Otherwise leave blank so prefers-color-scheme can apply.
if (storedTheme === 'dark' || storedTheme === 'light') {
root.setAttribute('data-theme', storedTheme === 'dark' ? 'dark' : '');
updateToggleUI(storedTheme === 'dark');
} else {
// If no stored value, we can detect system preference and set toggle UI accordingly
const prefersDark = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;
updateToggleUI(prefersDark);
}

// Helper to update toggle visuals & aria
function updateToggleUI(isDark) {
toggle.setAttribute('aria-pressed', isDark ? 'true' : 'false');
toggleText.textContent = isDark ? 'Light' : 'Dark'; // shows action to do
toggleIcon.textContent = isDark ? 'β˜€οΈ' : 'πŸŒ™';
}

// Toggle click handler
toggle.addEventListener('click', function () {
const isDarkNow = root.getAttribute('data-theme') === 'dark';
if (isDarkNow) {
// switch to light
root.removeAttribute('data-theme');
localStorage.setItem('theme', 'light');
updateToggleUI(false);
} else {
// switch to dark
root.setAttribute('data-theme', 'dark');
localStorage.setItem('theme', 'dark');
updateToggleUI(true);
}
});

// Optional: listen to system preference changes and apply only when user hasn't explicitly chosen
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', e => {
const stored = localStorage.getItem('theme');
if (!stored) {
updateToggleUI(e.matches);
if (e.matches) root.setAttribute('data-theme', 'dark');
else root.removeAttribute('data-theme');
}
});
})();
</script>
</body>
</html>

πŸ” Accessibility & Best Practices

Aria: tumia aria-pressed na aria-label kwenye button; au role="switch" kama unataka.

Keyboard: button inawezeshwa kwa keyboard by default (focusable). Ongeza focus style (tumeongeza outline).

Screen readers: Badilisha aria-pressed wakati wa toggle.

Non-JS fallback: kwa watumiaji wasiokuwa na JS, prefers-color-scheme inasaidia kuhifadhi default ya system. Unaweza pia kutoa server-side rendering kulingana na cookie.

Performance: tumia CSS variables badala ya inline styles nyingi. Hii inaleta transitions laini bila reflow kubwa.

Persistence: localStorage ni rahisi; kwa login systems unaweza kuhifadhi choice kwenye profile DB.

πŸ”§ Extensions za kujaribu

Add CSS variable set kwa --link, --border, --shadow ili uanze theming zaidi.

Use data-theme="auto" to indicate follow-system + a UI hint.

Save user choice to server via AJAX for logged-in users.

Animate background gradients or images cautiously (avoid motion sickness).

πŸ”— Links Za Kujifunza Zaidi (Faulink)

🌐 Faulink Official Website:
https://www.faulink.com/

πŸ“˜ Jifunze Web Design & Programming (Tutorials / Mifumo):
https://www.faulink.com/excel_mifumo.php

πŸ“² Piga / WhatsApp kwa msaada wa haraka:
https://wa.me/255693118509