The code behind this CSS theming
The foundation of this way of theming is CSS. Using HTML dataset to make it persistent. And use Javascript to set
and switch between themes.
The theme is executed by a dataset in the body tag and changed by Javascript Setting CSS variables and use them instead of #900 etc, the colors will be dynamic. Using hsl() this will be
even
easier to make a consistent theme - just edit the last percent to make it darker or lighter. Javascript is used to initialize (change body dataset and check for current theme) as well as used to set
desired theme and store this into localStorage. By using svg icons as "Symbols" without color you can change the color dynamically Using CSS you can set the css color variable to the svg symbols.
1. Set Theme constant in the HTML body dataset
<body data-theme="dodger">
/* And the Javascript line that changes this */
document.body.dataset.theme = localStorage.theme;
2. Use CSS variables to make it more DRY
[data-theme='default'] {
--bg: hsl(255, 99%, 98%);
--dark: hsl(255, 99%, 95%);
--medium: hsl(255, 99%, 78%);
--lite: hsl(255, 99%, 94%);
--hover: hsl(255, 99%, 88%);
--select: hsl(255, 99%, 93%);
--black: hsl(255, 0%, 20%);
--white: hsl(255, 30%, 99%);
--text_header: hsl(255, 70%, 50%);
--icn_header: hsl(255, 70%, 50%);
--icn: hsl(255, 70%, 50%);
--formbg: hsl(255, 99%, 97%);
--stop: hsl(0, 100%, 30%);
--ok: hsl(120,100%,30%);
}
[data-theme=indigo] {
--bg: hsl(255, 99%, 97%);
--dark: hsl(255, 99%, 65%);
--medium: hsl(255, 99%, 75%);
--darklite: hsl(255, 99%, 85%);
--lite: hsl(255, 99%, 97%);
--hover: hsl(255, 99%, 90%);
--select: hsl(255, 99%, 93%);
--black: hsl(0, 0%, 20%);
--darkgray: hsl(0, 0%, 40%);
--white: hsl(255, 30%, 99%);
--text_header: hsl(255, 70%, 98%);
--icn_header: hsl(255, 70%, 98%);
--icn: hsl(255, 70%, 50%);
--formbg: hsl(255, 99%, 97%);
--stop: hsl(0, 100%, 50%);
--ok: hsl(120,100%,50%);
}
[data-theme=dodger] {
--bg: hsl(210, 99%, 97%);
--dark: hsl(210, 99%, 65%);
--medium: hsl(210, 99%, 75%);
--darklite: hsl(210, 99%, 85%);
--lite: hsl(210, 99%, 97%);
--hover: hsl(210, 99%, 90%);
--select: hsl(210, 99%, 93%);
--black: hsl(0, 0%, 20%);
--darkgray: hsl(0, 0%, 40%);
--white: hsl(210, 30%, 99%);
--text_header: hsl(210, 70%, 98%);
--icn_header: hsl(210, 70%, 98%);
--icn: hsl(210, 70%, 50%);
--formbg: hsl(210, 99%, 97%);
--stop: hsl(0, 100%, 30%);
--ok: hsl(120,100%,30%);
}
[data-theme=barbie] {
--bg: hsl(300, 99%, 98%);
--dark: hsl(300, 99%, 65%);
--medium: hsl(300, 99%, 75%);
--darklite: hsl(300, 99%, 85%);
--lite: hsl(300, 99%, 97%);
--hover: hsl(300, 99%, 90%);
--select: hsl(300, 99%, 93%);
--black: hsl(0, 0%, 20%);
--white: hsl(300, 30%, 99%);
--darkgray: hsl(0, 0%, 40%);
--text_header: hsl(255, 70%, 98%);
--icn_header: hsl(255, 70%, 98%);
--icn: hsl(300, 70%, 50%);
--formbg: hsl(300, 99%, 97%);
--stop: hsl(0, 100%, 30%);
--ok: hsl(120,100%,30%);
}
[data-theme=classic] {
--bg: hsl(250, 20%, 97%);
--dark: hsl(250, 20%, 65%);
--medium: hsl(250, 20%, 75%);
--darklite: hsl(250, 20%, 85%);
--lite: hsl(250, 20%, 95%);
--hover: hsl(250, 20%, 80%);
--select: hsl(250, 20%, 80%);
--black: hsl(0, 0%, 20%);
--white: hsl(250, 30%, 99%);
--darkgray: hsl(0, 0%, 40%);
--text_header: hsl(250, 20%, 98%);
--icn_header: hsl(250, 20%, 98%);
--icn: hsl(250, 20%, 50%);
--formbg: hsl(250, 99%, 97%);
--stop: hsl(0, 100%, 30%);
--ok: hsl(120,100%,30%);
}
[data-theme=snowflake] {
--bg: hsl(250, 20%, 97%);
--dark: hsl(250, 20%, 97%);
--medium: hsl(250, 20%, 75%);
--darklite: hsl(250, 20%, 85%);
--lite: hsl(250, 20%, 95%);
--hover: hsl(250, 20%, 90%);
--select: hsl(250, 20%, 90%);
--black: hsl(0, 0%, 20%);
--white: hsl(250, 30%, 99%);
--darkgray: hsl(0, 0%, 40%);
--text_header: hsl(0, 0%, 20%);
--icn_header: hsl(0, 0%, 20%);
--icn: hsl(0, 0%, 20%);
--formbg: hsl(250, 99%, 97%);
--stop: hsl(0, 100%, 30%);
--ok: hsl(120,100%,30%);
}
3. Set, store and display theme using Javascript
// set to default if theme is empty
window.addEventListener('load', (event) => {
if (localStorage.theme === "undefined") {
set_theme('default')
}
document.body.dataset.theme = localStorage.theme;
});
function set_theme(name) {
document.body.dataset.theme = name;
localStorage.setItem("theme", name);
}
function set_prefs(theme,name){
set_theme(theme)
document.getElementById('theme').innerHTML = name
document.getElementById('details').removeAttribute('open')
}
// store from accordion
let themes = document.getElementById("select").querySelectorAll("li")
themes.forEach(function(theme) {
theme.addEventListener("click", function() {
document.getElementById('theme').dataset.theme = this.dataset.theme
set_prefs(this.dataset.theme, this.innerHTML)
})
});
// prepare the accordion when loading page
function init() {
for (let item of themes) {
if (item.dataset.theme === localStorage.theme){
set_prefs(item.dataset.theme,item.innerHTML)
}
}
}
init()
4. Use SVG Symbol technique to affect svg icons
<!--<?xml version="1.0" encoding="UTF-8"?>-->
<svg xmlns="http://www.w3.org/2000/svg" style="display: none">
<symbol id="hamburger" viewBox="0 0 32 32">
<path fill="none" d="M0 0h32v32h-32v-32z"></path>
<path d="M10.377 12.116h12.389v1.418h-12.389v-1.418z"></path>
<path d="M10.377 15.424h12.389v1.418h-12.389v-1.418z"></path>
<path d="M10.377 18.731h12.389v1.417h-12.389v-1.417z"></path>
<path fill="#f1f1f1" d="M19.495 11.176h0.026v0.053h-0.026v-0.053z"></path>
</symbol>
<symbol id="hub" viewBox="0 0 56 56">
<path d="M20.88,20.83h3.417c0.158,0,0.285,0.127,0.285,0.285v3.417c0,0.158-0.127,0.285-0.285,0.285H20.88
c-0.157,0-0.284-0.127-0.284-0.285v-3.417C20.596,20.957,20.723,20.83,20.88,20.83z" />
<path d="M26.29,20.83h3.418c0.156,0,0.284,0.127,0.284,0.285v3.417c0,0.158-0.128,0.285-0.284,0.285H26.29
c-0.156,0-0.284-0.127-0.284-0.285v-3.417C26.006,20.957,26.134,20.83,26.29,20.83z" />
<path d="M31.701,20.83h3.417c0.157,0,0.285,0.127,0.285,0.285v3.417c0,0.158-0.128,0.285-0.285,0.285h-3.417
c-0.157,0-0.285-0.127-0.285-0.285v-3.417C31.416,20.957,31.544,20.83,31.701,20.83z" />
<path d="M20.88,26.24h3.417c0.158,0,0.285,0.127,0.285,0.285v3.417c0,0.158-0.127,0.285-0.285,0.285H20.88
c-0.157,0-0.284-0.127-0.284-0.285v-3.417C20.596,26.368,20.723,26.24,20.88,26.24z" />
<path d="M26.29,26.24h3.418c0.156,0,0.284,0.127,0.284,0.285v3.417c0,0.158-0.128,0.285-0.284,0.285H26.29
c-0.156,0-0.284-0.127-0.284-0.285v-3.417C26.006,26.368,26.134,26.24,26.29,26.24z" />
<path d="M31.701,26.24h3.417c0.157,0,0.285,0.127,0.285,0.285v3.417c0,0.158-0.128,0.285-0.285,0.285h-3.417
c-0.157,0-0.285-0.127-0.285-0.285v-3.417C31.416,26.368,31.544,26.24,31.701,26.24z" />
<path d="M20.88,31.65h3.417c0.158,0,0.285,0.128,0.285,0.285v3.417c0,0.157-0.127,0.285-0.285,0.285H20.88
c-0.157,0-0.284-0.128-0.284-0.285v-3.417C20.596,31.778,20.723,31.65,20.88,31.65z" />
<path d="M26.29,31.65h3.418c0.156,0,0.284,0.128,0.284,0.285v3.417c0,0.157-0.128,0.285-0.284,0.285H26.29
c-0.156,0-0.284-0.128-0.284-0.285v-3.417C26.006,31.778,26.134,31.65,26.29,31.65z" />
<path d="M31.701,31.65h3.417c0.157,0,0.285,0.128,0.285,0.285v3.417c0,0.157-0.128,0.285-0.285,0.285h-3.417
c-0.157,0-0.285-0.128-0.285-0.285v-3.417C31.416,31.778,31.544,31.65,31.701,31.65z" />
</symbol>
</svg>
5. Style the svg using CSS stroke and fill
#icn_hamburger svg:hover {
stroke: var(--stop);
fill: var(--stop);
}