Little theme switcher between bright and dark mode built with CSS custom properties and JavaScript which changes them on toggle click. Inspired by Florin Pop's coding challenges you should definitely check.
Created
December 22, 2021 04:36
-
-
Save Haeyzed/f8788b642b55537625bb5db6fda79ffd to your computer and use it in GitHub Desktop.
Light/Dark Theme Toggle with CSS Variables (CSS, JS)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<div class="wrapper"> | |
<div class="circle"></div> | |
<article> | |
<h2>Too bright?</h2> | |
<p>Look no further. Here we have a buttony twist on the classic checkbox toggler to carelessly toggle site theme between <span id="shift">lighter and darker<span>.</p><p>Go ahead and toggle a toggler below.</p> | |
<p>👇 👇 👇</p> | |
</article> | |
<button class="toggle" id="toggle"></button> | |
</div> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
Inspired by Florin Pop's coding challenges, you can check them here: https://www.florin-pop.com/blog/2019/03/weekly-coding-challenge/ | |
*/ | |
// UI Elements | |
const toggle = document.getElementById("toggle"), | |
circle = document.querySelector(".circle"), | |
body = document.querySelector("body"); | |
let span = document.getElementById("shift"); | |
let theme = "bright"; | |
// Helper function for setting theme parameters | |
// "params" needs to be written like object {"key1": "value1", "key2": "value2", ...} | |
function setStyles(element, params) { | |
for(let i in params) { | |
element.style.setProperty(i, params[i]); | |
} | |
} | |
// Main logic | |
function themeChange() { | |
theme = theme === "bright" ? "dark" : "bright"; | |
document.querySelector("article > h2").textContent = `Too ${theme}?`; | |
if(theme === "bright") { | |
setStyles(body, {"--background": "#FBFFF1", "--text": "#3C3744", "--accent": "#F49F6E"}); | |
toggle.classList.remove("clicked"); | |
circle.classList.remove("clicked"); | |
span.textContent = `brighter and darker.`; | |
} else { | |
setStyles(body, {"--background": "#3C3744", "--text": "#FBFFF1", "--accent": "#C41E3D"}); | |
toggle.classList.add("clicked"); | |
circle.classList.add("clicked"); | |
span.textContent = `darker and brighter.`; | |
} | |
} | |
// Event listener for toggle button click | |
toggle.addEventListener("click", themeChange); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* Imports */ | |
@import url('https://fonts.googleapis.com/css?family=Roboto|Viga&display=swap'); | |
/* Resets */ | |
*, *::after, *::before { | |
box-sizing: border-box; | |
margin: 0; | |
padding: 0; | |
} | |
/* Button resets & styles */ | |
button { | |
display: block; | |
border: none; | |
color: inherit; | |
padding: 0; | |
margin: 0; | |
cursor: pointer; | |
} | |
button:focus, button:active { | |
outline: none; | |
} | |
button:active { | |
transform: scale(1); | |
} | |
/* General styles */ | |
body { | |
--background: #FBFFF1; | |
--text: #3C3744; | |
--accent: #F49D6E; | |
background-color: var(--background); | |
font-family: 'Roboto', sans-serif; | |
color: var(--text); | |
height: 100vh; | |
transition: color ease-out 250ms; | |
overflow-x: hidden; | |
} | |
.wrapper { | |
margin: auto; | |
height: 100%; | |
max-width: 540px; | |
display: flex; | |
flex-direction: column; | |
align-items: center; | |
justify-content: center; | |
padding: 1rem; | |
} | |
article { | |
margin-bottom: 1rem; | |
text-align: center; | |
} | |
h2 { | |
font-size: 2.2em; | |
font-family: 'Viga', sans-serif; | |
} | |
h2, * + p { | |
margin-bottom: 1rem; | |
} | |
article > p:nth-of-type(2) { | |
margin-top: -1rem; | |
} | |
/* Emoji custom styles */ | |
article > p:last-of-type { | |
color: transparent; | |
text-shadow: 0 0 0 var(--text); | |
transition: text-shadow ease-out 250ms; | |
} | |
/* Toggle button styles */ | |
.toggle { | |
background-color: var(--text); | |
min-width: 80px; | |
min-height: 40px; | |
margin-bottom: 1rem; | |
position: relative; | |
border: 2px solid; | |
border-radius: 30px; | |
cursor: pointer; | |
transition: background-color ease-out 250ms; | |
} | |
.toggle::after { | |
content: ""; | |
position: absolute; | |
background-color: var(--background); | |
top: 0; | |
left: 0; | |
width: 50%; | |
height: 100%; | |
border-radius: 30px; | |
transition: transform ease-out 250ms; | |
} | |
/* Active (dark mode) class for animating transition on toggle button*/ | |
.toggle.clicked::after { | |
transform: translateX(100%); | |
} | |
/* "Sun to moon" graphics and animation */ | |
.circle, .circle::after { | |
background-color: var(--accent); | |
min-width: 300px; | |
min-height: 300px; | |
border-radius: 50%; | |
margin-bottom: 2rem; | |
} | |
.circle { | |
transform: rotate(-25deg); | |
transition: background-color ease-out 250ms; | |
} | |
.circle::after { | |
content: ""; | |
position: absolute; | |
top: 0; | |
left: 0; | |
transform: translateY(-100%); | |
background-color: var(--background); | |
transition: transform ease-out 250ms; | |
transition-delay: 20ms; | |
} | |
.circle.clicked::after { | |
transform: translateY(-30%); | |
} | |
@media screen and (max-height: 560px) { | |
.circle, .circle::after { | |
margin-bottom: calc(-6rem - 12vh); | |
z-index: -1; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment