Dark / Light Mode
A theme switcher using a checkbox, CSS custom properties, and no JS.
Published May 19, 2026
Demo
This area reacts to the theme toggle — background, text, and border all change.
HTML
<input class="theme-check" type="checkbox" id="theme1">
<label class="theme-toggle" for="theme1">
<span class="theme-track"></span>
Dark mode
</label>
<div class="theme-preview">Content area</div>
CSS
.theme-check { display: none; }
.theme-track {
width: 52px;
height: 28px;
background: #f0c040;
border-radius: 999px;
position: relative;
transition: background .3s;
}
.theme-track::after {
content: "";
position: absolute;
top: 3px; left: 3px;
width: 22px; height: 22px;
background: #fff;
border-radius: 50%;
transition: transform .3s;
}
.theme-check:checked + .theme-toggle .theme-track {
background: #2d2d4e;
}
.theme-check:checked + .theme-toggle .theme-track::after {
transform: translateX(24px);
}
.theme-preview {
background: #fffbe6;
color: #333;
transition: background .3s, color .3s;
}
.theme-check:checked ~ .theme-preview {
background: #1a1a2e;
color: #e0e0ff;
}
How it works
A hidden checkbox holds the theme state. A sibling combinator (~) lets elements further down the DOM respond to its :checked state. For a real page-wide theme, put the checkbox near the top of the DOM and use the ~ combinator on the body or a wrapper element with CSS custom property overrides.