Light / Dark Mode Toggle with HTML, CSS & JavaScript
20 DAYS 20 PROJECT CHALLENGE
Day #15
Project Overview
A simple and modern Light/Dark mode theme switcher built using CSS variables and LocalStorage.
With a single click, the user can switch the entire websiteโs theme, and the preference is saved so the site loads in the chosen theme even after refresh or reopening the browser.
This project helps you understand:
- How to use CSS variables for global theme colors.
- How to toggle theme classes with JavaScript.
- How to save & load user preferences using LocalStorage.
- How to update UI icons and transitions for a smooth effect.
Key Features
- One-click theme toggle (light โ dark).
- Smooth color transitions.
- Theme icon change (sun/moon).
- Persistent theme using LocalStorage.
- Clean UI + responsive layout.
- Uses CSS variables to maintain entire site theme.
HTML Code
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width,initial-scale=1"/>
<title>Day 15 — Light/Dark Mode Toggle</title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<main class="card" role="main">
<header class="head">
<h1>Day 15: Light / Dark Mode Toggle</h1>
<p class="lead">Switch themes with one click. Your preference is saved.</p>
<button id="themeToggle" class="theme-btn" aria-label="Toggle Theme">
<span id="themeIcon">๐</span>
</button>
</header>
<section>
<p>
This is a demo of a light/dark theme switcher using CSS variables and LocalStorage.
Click on the moon/sun icon above to change the theme.
</p>
</section>
<details>
<summary>How it works (short)</summary>
<p class="small">
The website uses a <code>data-theme</code> attribute on the HTML tag.
CSS variables define the theme colors. JavaScript toggles the attribute
and saves the choice in LocalStorage. On page load, the saved theme is applied.
</p>
</details>
</main>
<script src="script.js"></script>
</body>
</html>
CSS Code
/* THEME VARIABLES */
:root {
--bg: #ffffff;
--text: #1e293b;
--card-bg: #f1f5f9;
--accent: #7c3aed;
}
html[data-theme="dark"] {
--bg: #002252;
--text: #e2e8f0;
--card-bg: #1e293b;
--accent: #c084fc;
}
html, body {
height: 100%;
background: var(--bg);
color: var(--text);
font-family: Inter, system-ui, sans-serif;
margin: 0;
transition: background 0.3s ease, color 0.3s ease;
}
/* CARD */
.card {
width: min(700px, 92%);
margin: 40px auto;
background: var(--card-bg);
padding: 22px;
border-radius: 14px;
box-shadow: 0 8px 20px rgba(0, 0, 0, 0.15);
transition: background 0.3s ease;
}
.head {
display: flex;
justify-content: space-between;
align-items: center;
}
.lead {
margin-top: -10px;
font-size: 14px;
opacity: 0.8;
}
/* TOGGLE BUTTON */
.theme-btn {
background: var(--accent);
border: none;
color: white;
font-size: 22px;
border-radius: 50%;
width: 44px;
height: 44px;
cursor: pointer;
box-shadow: 0 4px 14px rgba(124, 58, 237, 0.4);
transition: transform 0.2s ease;
}
.theme-btn:hover {
transform: scale(1.1);
}
.small {
font-size: 13px;
opacity: 0.8;
}
Javascript Code
// Day 15: Light/Dark Mode Toggle
// Uses data-theme attribute + LocalStorage
const themeToggle = document.getElementById('themeToggle');
const themeIcon = document.getElementById('themeIcon');
// Load saved theme from LocalStorage
const savedTheme = localStorage.getItem('theme');
if (savedTheme) {
document.documentElement.setAttribute('data-theme', savedTheme);
themeIcon.textContent = savedTheme === 'dark' ? 'โ๏ธ' : '๐';
}
// Toggle theme
themeToggle.addEventListener('click', () => {
const current = document.documentElement.getAttribute('data-theme');
const newTheme = current === 'dark' ? 'light' : 'dark';
// Apply new theme
document.documentElement.setAttribute('data-theme', newTheme);
// Save in LocalStorage
localStorage.setItem('theme', newTheme);
// Update icon
themeIcon.textContent = newTheme === 'dark' ? 'โ๏ธ' : '๐';
});
Subscribe
0 Comments
Oldest
Newest
Most Voted
Inline Feedbacks
View all comments
Related Projects
Day 13 : Currency Converter
Converts one currency to another using real-time exchange rates.
Concepts: API fetch, DOM updates.
Day 17 : Clipboard Copy Tool
Click a button to copy text to the clipboard.
Concepts: Clipboard API, DOM events.
Day 18 : Text-to-Speech Converter
Converts entered text into speech.
Concepts: Web Speech API.