<div class="theme-switcher__container">
<div class="theme-switcher flex mb-4 sm--mb-0 text-tiny">
<div class="theme-switcher__option flex flex-align-center mr-2">
<input class="theme-switcher__input" type="radio" id="theme-light" name="theme-selector" value="light" \>
<label class="theme-switcher__label inline-block px-3 py-1 capitalize text-action-base border-radius-small" for="theme-light">
Light
</label>
<svg class="theme-switcher__icon theme-switcher__icon--sun" width="50" height="50" viewBox="-50 -50 100 100">
<defs>
<polygon id="sun-ray" points="0,0 -20,0 0,-50 20,0" fill="#ff851b" />
</defs>
<g class="svg-sun-rays">
<use href="#sun-ray" />
<use href="#sun-ray" transform="rotate(45)" />
<use href="#sun-ray" transform="rotate(90)" />
<use href="#sun-ray" transform="rotate(135)" />
<use href="#sun-ray" transform="rotate(180)" />
<use href="#sun-ray" transform="rotate(225)" />
<use href="#sun-ray" transform="rotate(270)" />
<use href="#sun-ray" transform="rotate(315)" />
</g>
<circle class="svg-sun" cy="0" cx="0" r="30" fill="#ff851b" stroke-width="5px" stroke="white" />
</svg>
</div>
<div class="theme-switcher__option flex flex-align-center mr-2">
<input class="theme-switcher__input" type="radio" id="theme-dark" name="theme-selector" value="dark" \>
<label class="theme-switcher__label inline-block px-3 py-1 capitalize text-action-base border-radius-small" for="theme-dark">
Dark
</label>
<svg class="theme-switcher__icon theme-switcher__icon--moon" width="50" height="50" viewBox="-50 -50 100 100">
<circle cy="0" cx="0" r="45" fill="#7fdbff" />
<circle class="svg-moon-ellipse" cy="0" cx="-35" r="45" fill="white" />
</svg>
</div>
</div>
</div>
.theme-switcher__container {
display: flex;
width: 100vw;
height: 100vh;
align-items: center;
justify-content: center;
}
.theme-switcher {
display: flex;
padding: 1rem;
}
.theme-switcher__option {
position: relative;
display: flex;
padding: 0.25rem;
margin: 0 0.5rem;
min-width: 110px;
align-items: center;
justify-content: space-between;
border: 2px solid black;
border-radius: 5px;
overflow: hidden;
}
.theme-switcher__input {
opacity: 0;
position: fixed;
width: 0;
&:checked + .theme-switcher__label {
font-weight: 700;
text-decoration: underline;
}
&:focus + .theme-switcher__label {
// outline: 2px solid red;
// outline-offset: -3px;
}
}
.theme-switcher__label {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
display: flex;
padding: 0.25rem 0.5rem;
margin-right: 5px;
align-items: center;
&:hover,
&:focus {
cursor: pointer;
}
}
.theme-switcher__icon {
margin-left: auto;
}
.svg-sun-rays {
transform-origin: 50%;
}
.svg-moon-ellipse {
transform-origin: 0% 50%;
}
View Compiled
const animation = {
duration: 0.5,
black: "black",
white: "white",
dark: "#060f94",
light: "#fcf4a3"
};
(function () {
const themeRadios = document.getElementsByClassName("theme-switcher__input");
function addEventListeners() {
for (var i = 0, max = themeRadios.length; i < max; i++) {
themeRadios[i].onclick = function (el) {
const selectedTheme = el["srcElement"]["defaultValue"];
setTheme(selectedTheme);
};
}
}
function setTheme(theme) {
const themeRadio = document.getElementById(`theme-${theme}`),
themeSwitch = document.getElementsByClassName("theme-switcher")[0],
body = document.getElementsByTagName("BODY")[0],
lightTheme = theme === "light";
themeRadio.checked = true;
localStorage.setItem("theme", theme);
themeSwitch.classList.add(
lightTheme ? "theme-switcher--light" : "theme-switcher--dark"
);
body.classList.add(lightTheme ? "theme-light" : "theme-dark");
themeSwitch.classList.remove(
lightTheme ? "theme-switcher--dark" : "theme-switcher--light"
);
body.classList.remove(lightTheme ? "theme-dark" : "theme-light");
const tl = gsap.timeline({ defaults: { duration: animation.duration } });
tl.to(
"body",
{
backgroundColor: lightTheme ? animation.light : animation.dark,
color: lightTheme ? animation.black : animation.white
},
0
);
tl.to(
".theme-switcher__option",
{
borderColor: lightTheme ? animation.black : animation.white
},
0
);
tl.to(
".svg-sun",
{
stroke: lightTheme ? animation.light : animation.dark
},
0
);
tl.to(
".svg-moon-ellipse",
{
fill: lightTheme ? animation.light : animation.dark
},
0
);
tl.to(
".theme-switcher__icon--moon",
{
yPercent: lightTheme ? 115 : 0
},
0
);
tl.to(
".theme-switcher__icon--sun",
{
yPercent: lightTheme ? 0 : 115
},
0
);
tl.to(
".svg-sun-rays",
{
scale: lightTheme ? 1 : 0
},
animation.duration
);
tl.to(
".svg-moon-ellipse",
{
scale: lightTheme ? 0 : 1
},
animation.duration
);
}
addEventListeners();
})();
View Compiled
This Pen doesn't use any external CSS resources.