<div class="container">
<section class="header">
<h1>Light / Dark Mode Toggle</h1>
<label class="switch">
<input type="checkbox" id="theme-toggle">
<span class="slider"></span>
</label>
</section>
<p>This example demonstrates a toggle switch that adapts to your system’s dark or light mode preference using CSS variables.</p>
<ul>
<li><strong>System Preference :</strong> The toggle and page theme automatically align with your system’s mode, providing an intuitive default.</li>
<li><strong>Switch behavior:</strong> Click the switch to change the page’s background and text colors between light and dark mode.</li>
</ul>
<p>Try toggling the switch and adjusting your system’s dark mode setting to see the effect in action!</p>
<a href="https://www.thingsaboutweb.dev/en/posts/css-variables-part-2">See full article here</a>
</div>
/* Define CSS variables for color modes */
:root {
--ON: initial; /* Default state variable to use for switching colors */
--OFF: ; /* Alternative state variable for switching colors */
/* Set default color variables based on light mode */
--light: var(--ON);
--dark: var(--OFF);
/* Define custom properties for colors used in light and dark modes */
--background-color: var(--light, #fbfbfb) var(--dark, #121212);
--container-background-color: var(--light, #ebebeb) var(--dark, #555555);
--headline-color: var(--light, #0077ee) var(--dark, #94b2e6);
--text-color: var(--light, #333333) var(--dark, #e0e0e0);
}
/* Switch color modes when the checkbox (toggle) is checked */
:root:has(input[type="checkbox"]:checked) {
--light: var(--OFF);
--dark: var(--ON);
}
/* Invert the color behavior for system dark mode */
@media (prefers-color-scheme: dark) {
:root {
--light: var(--OFF);
--dark: var(--ON);
}
/* Toggle to light mode colors when checkbox is checked in dark mode */
:root:has(input[type="checkbox"]:checked) {
--light: var(--ON);
--dark: var(--OFF);
}
}
/* Body styles with background and text color transitions */
body {
background-color: var(--background-color);
color: var(--text-color);
transition: background-color 0.5s, color 0.5s;
}
/* Container styling with background color based on mode */
.container {
background-color: var(--container-background-color);
color: var(--text-color);
margin: 5em auto;
padding: 2em;
border-radius: 15px;
width: 30em;
max-width: 80vw;
transition: background-color 0.5s;
}
/* Header styling for a flex layout between toggle switch and title */
.header {
display: flex;
justify-content: space-between;
align-items: center;
max-width: 100%;
}
/* Heading color based on mode with transition effect */
h1 {
color: var(--headline-color);
transition: color 0.5s;
}
/* Toggle Switch Styles */
.switch {
position: relative;
display: inline-block;
width: 60px;
height: 34px;
}
/* Hide the checkbox element to style a custom switch */
.switch input {
opacity: 0;
width: 0;
height: 0;
}
/* Slider styling for the switch background */
.slider {
position: absolute;
cursor: pointer;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: var(--slider-bg, #ccc);
transition: 0.4s;
border-radius: 34px;
}
/* Slider knob styling */
.slider:before {
position: absolute;
content: "";
height: 26px;
width: 26px;
left: 4px;
bottom: 4px;
background-color: white;
transition: 0.4s;
border-radius: 50%;
}
/* Dark mode styles: make the switch look "checked" by default */
@media (prefers-color-scheme: dark) {
.slider {
background-color: #94b2e6;
}
.slider:before {
transform: translateX(26px); /* Move knob to the right */
}
/* Invert checked state in dark mode to look "unchecked" */
input:checked + .slider {
background-color: #ccc;
}
input:checked + .slider:before {
transform: translateX(0); /* Move knob to the left */
}
}
/* Light mode styles: make the switch look "unchecked" by default */
@media (prefers-color-scheme: light) {
.slider {
background-color: #ccc;
}
.slider:before {
transform: translateX(0); /* Knob on the left */
}
/* Invert checked state in light mode to look "checked" */
input:checked + .slider {
background-color: #94b2e6;
}
input:checked + .slider:before {
transform: translateX(26px); /* Move knob to the right */
}
}
This Pen doesn't use any external CSS resources.
This Pen doesn't use any external JavaScript resources.