A smooth dark/light mode toggle that persists the user's preference using
localStorage.
The toggle animates between a sun and moon icon and applies a
dark class to the body so you can style everything with CSS.
How to Use?
Add the HTML toggle button anywhere in your page, paste the CSS and JS.
Style your dark mode overrides under body.dark and the toggle handles the rest automatically.
Credits
Built with localStorage, classList toggling, and zero dependencies.
<!-- Place this button wherever you want the toggle -->
<button class="theme-toggle" id="theme-toggle" aria-label="Toggle dark mode">
<span class="toggle-track">
<span class="toggle-thumb"></span>
</span>
<span class="toggle-icon"></span>
</button>
body {
background: #ffffff;
color: #18181b;
transition: background 0.3s ease, color 0.3s ease;
}
body.dark {
background: #09090b;
color: #e4e4e7;
}
.theme-toggle {
display: inline-flex;
align-items: center;
gap: 0.5rem;
background: none;
border: none;
cursor: pointer;
padding: 0.25rem;
}
.toggle-track {
width: 44px;
height: 24px;
background: #d4d4d8;
border-radius: 999px;
position: relative;
transition: background 0.3s ease;
display: block;
}
body.dark .toggle-track {
background: #8b5cf6;
}
.toggle-thumb {
position: absolute;
top: 3px;
left: 3px;
width: 18px;
height: 18px;
border-radius: 50%;
background: #ffffff;
box-shadow: 0 1px 4px rgba(0,0,0,0.3);
transition: transform 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);
}
body.dark .toggle-thumb {
transform: translateX(20px);
}
.toggle-icon {
font-size: 1.1rem;
transition: transform 0.4s ease;
display: inline-block;
}
const toggle = document.getElementById('theme-toggle');
const icon = toggle.querySelector('.toggle-icon');
const MOON = '\u263E';
const SUN = '\u2600';
const saved = localStorage.getItem('theme');
if (saved === 'dark') {
document.body.classList.add('dark');
icon.textContent = SUN;
} else {
icon.textContent = MOON;
}
toggle.addEventListener('click', () => {
const isDark = document.body.classList.toggle('dark');
localStorage.setItem('theme', isDark ? 'dark' : 'light');
icon.style.transform = 'rotate(180deg) scale(0)';
setTimeout(() => {
icon.textContent = isDark ? SUN : MOON;
icon.style.transform = 'rotate(0deg) scale(1)';
}, 200);
});