This code implements a theme switcher using CSS variables and JavaScript. The theme switcher allows users to switch between different themes, such as dark, sunset, sunrise, and light. Each theme is defined by a set of CSS variables that control the colors used in the user interface.
The code dynamically changes the CSS variables on the root element based on the selected theme. It also updates the active state of the theme buttons and adjusts the position of the theme grid based on the selected theme.
The theme switcher provides an intuitive way for users to switch between different visual styles and customize the look and feel of the website or application. By using CSS variables, the code offers flexibility and easy maintenance, as the themes can be easily modified by changing the CSS variable values.
How to Create Theme Switcher using CSS Variables and JavaScript
First of all, load the Google Fonts by adding the following CDN links into the head tag of your HTML document. (Optional)
<link rel="preconnect" href="https://fonts.googleapis.com"> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> <link href="https://fonts.googleapis.com/css2?family=Figtree:wght@400;700&display=swap" rel="stylesheet">
Create the HTML structure for theme swichter as follows:
<div class="c-card"> <button class="c-theme" id="themePicker"></button> <h1 class="c-card__title">Variable Themes</h1> <p class="c-card__description">Cycle through 4 themes, from darkest to lightest.</p> <div class="c-theme-grid" id="themeGrid"></div><a class="c-button" id="button">Cycle Theme</a> </div>
Style the switcher interface using the following CSS styles:
@charset "UTF-8"; :root { --dark-bg: #101214; --dark-border: #22272B; --dark-surface: #161A1D; --dark-text-primary: #DEE4EA; --dark-text-secondary: #738496; --dark-primary: #1D7AFC; --dark-text-inverse: #FFFFFF; --sunset-bg: #151c19; --sunset-border: #424f4a; --sunset-surface: #2f3834; --sunset-text-primary: #ecd2c5; --sunset-text-secondary: #C0AB92; --sunset-primary: #C0AB92; --sunset-text-inverse: #151c19; --sunrise-bg: #ecd2c5; --sunrise-border: #d7c9c6; --sunrise-surface: #f3e8e5; --sunrise-text-primary: #4f2733; --sunrise-text-secondary: #685844; --sunrise-primary: #a04d66; --sunrise-text-inverse: #f3e8e5; --light-bg: #F7F8F9; --light-border: #F1F2F4; --light-surface: #FFFFFF; --light-text-primary: #091E42; --light-text-secondary: #626F86; --light-primary: #1D7AFC; --light-text-inverse: #FFFFFF; --bg: var(--dark-bg); --border: var(--dark-border); --surface: var(--dark-surface); --text-primary: var(--dark-text-primary); --text-secondary: var(--dark-text-secondary); --primary: var(--dark-primary); --text-inverse: var(--dark-text-inverse); } *, *:before, *:after { box-sizing: border-box; } html { box-sizing: inherit; font-size: 62.5%; } html, body { margin: 0; padding: 0; width: 100%; height: 100%; } body { font-size: 1.6rem; font-family: "Figtree", system-ui, sans-serif; display: flex; align-items: center; justify-content: center; padding: 1.2rem; background: var(--bg); color: var(--text-secondary); } .cd__main{ max-width: 1280px !important; } .c-card { width: 100%; max-width: 650px; border: 1px solid var(--border); border-radius: 1.6rem; padding: 3.2rem; background: var(--surface); position: relative; box-shadow: 0.3px 0.5px 0.7px rgba(0, 0, 0, 0.08), 0.8px 1.6px 2px -0.8px rgba(0, 0, 0, 0.08), 2.1px 4.1px 5.2px -1.7px rgba(0, 0, 0, 0.08), 5px 10px 12.6px -2.5px rgba(0, 0, 0, 0.08); } .c-card__title { margin: 0 0 0.8rem; padding: 0; line-height: 1.2; font-size: 4rem; color: var(--text-primary); } .c-card__description { margin: 0; padding: 0; line-height: 150%; font-size: 2rem; color: var(--text-secondary); } .c-button { display: inline-flex; padding: 1.2rem 2rem; background: var(--primary); border-radius: 0.8rem; line-height: 1; cursor: pointer; color: var(--text-inverse); font-weight: 700; user-select: none; position: relative; transition: all 120ms ease-out; } .c-button:hover, .c-button:focus { outline: none; transform: scale(1.03); } .c-theme { position: absolute; top: 2.4rem; right: 2.4rem; width: 4rem; height: 4rem; cursor: pointer; display: inline-block; overflow: hidden; padding: 0; margin: 0; background: transparent; color: var(--text-primary); border: 1px solid transparent; border-radius: 0.8rem; padding: 0.4rem; transition: all 120ms ease-out; } .c-theme:hover, .c-theme:focus { border-color: var(--border); } .c-theme:after, .c-theme:before { content: ""; position: absolute; z-index: 10; } .c-theme:after { top: 0; left: 0; right: 0; height: 0.8rem; background: linear-gradient(to bottom, var(--surface), transparent); } .c-theme:before { bottom: 0; left: 0; right: 0; height: 0.8rem; background: linear-gradient(to top, var(--surface), transparent); } .c-theme:focus { outline: none; } .c-theme__grid { position: relative; width: 3.2rem; transition: all 240ms ease-out; } .c-theme svg { width: 3.2rem; height: 3.2rem; } .c-theme svg:focus { outline: none; } .c-box { display: flex; flex-direction: column; background: var(--bg); color: var(--text-secondary); position: relative; padding: 1.6rem; border-radius: 1.2rem; border: 1px solid var(--border); user-select: none; cursor: pointer; transition: all 120ms ease-out; } .c-box:hover, .c-box:focus { transform: scale(1.03); } .c-box__title { display: flex; align-items: center; width: 100%; } .c-box__icon { width: 1.6rem; height: 1.6rem; margin-right: 0.4rem; } .c-box__swatches { display: flex; flex-wrap: wrap; margin-top: 0.8rem; } .c-box--active { outline: 4px solid var(--primary); } .c-box--active:after { content: "✓"; position: absolute; top: -1.2rem; right: -1.2rem; height: 2.4rem; width: 2.4rem; background: var(--primary); border-radius: 999px; color: var(--text-inverse); display: inline-flex; align-items: center; justify-content: center; } .c-swatch { width: 2rem; height: 2rem; display: inline-block; border-radius: 999px; border: 1px solid var(--border); margin-right: -0.8rem; box-shadow: 0px 1px 1px rgba(0, 0, 0, 0.12), 0px 0px 0px 1px rgba(0, 0, 0, 0.08); } .c-theme-grid { display: grid; grid-template-columns: repeat(4, 1fr); grid-gap: 1.6rem; margin: 3.2rem 0; } @media (max-width: 700px) { .c-theme-grid { grid-template-columns: repeat(2, 1fr); } }
Finally, add the following JavaScript function to activate the theme switcher.
const themes = ['dark', 'sunset', 'sunrise', 'light']; let count = 0; const themePicker = document.getElementById('themePicker'); const themeList = document.getElementById('themeGrid'); // Change the CSS variables on the root element, depending on the curent theme const changeTheme = (theme) => { if(count < 3) { count += 1; } else { count = 0 } document.documentElement.style.setProperty('--bg', `var(--${theme}-bg)`); document.documentElement.style.setProperty('--border', `var(--${theme}-border)`); document.documentElement.style.setProperty('--surface', `var(--${theme}-surface)`); document.documentElement.style.setProperty('--text-primary', `var(--${theme}-text-primary)`); document.documentElement.style.setProperty('--text-secondary', `var(--${theme}-text-secondary)`); document.documentElement.style.setProperty('--primary', `var(--${theme}-primary)`); document.documentElement.style.setProperty('--text-inverse', `var(--${theme}-text-inverse)`); const themeGrid = themePicker.querySelector('.c-theme__grid') if(themeList.querySelector('.c-box--active')) { themeList.querySelector('.c-box--active').classList.remove('c-box--active') } themeList.querySelectorAll('.c-box').forEach(item => { if(item.dataset.theme === theme) { item.classList.add('c-box--active') } }) switch(theme) { case theme = 'dark': themeGrid.style.top = '0' break; case theme = 'sunset': themeGrid.style.top = '-3.6rem' break; case theme = 'sunrise': themeGrid.style.top = '-7.1rem' break; case theme = 'light': themeGrid.style.top = '-10.7rem' break; } } // Define Icons const darkIcon = `<svg fill="currentColor" aria-hidden="true" viewBox="0 0 24 24" tabindex="-1" title="Dark"><path d="M10 2c-1.82 0-3.53.5-5 1.35C7.99 5.08 10 8.3 10 12s-2.01 6.92-5 8.65C6.47 21.5 8.18 22 10 22c5.52 0 10-4.48 10-10S15.52 2 10 2z"></path></svg>` const sunsetIcon = `<svg fill="currentColor" aria-hidden="true" viewBox="0 0 24 24" tabindex="-1" title="Sunset"><path d="M20 8.69V4h-4.69L12 .69 8.69 4H4v4.69L.69 12 4 15.31V20h4.69L12 23.31 15.31 20H20v-4.69L23.31 12 20 8.69zM12 18c-.89 0-1.74-.2-2.5-.55C11.56 16.5 13 14.42 13 12s-1.44-4.5-3.5-5.45C10.26 6.2 11.11 6 12 6c3.31 0 6 2.69 6 6s-2.69 6-6 6z"></path></svg>` const sunriseIcon = `<svg fill="currentColor" aria-hidden="true" viewBox="0 0 24 24" tabindex="-1" title="Sunrise"><path d="M20 15.31 23.31 12 20 8.69V4h-4.69L12 .69 8.69 4H4v4.69L.69 12 4 15.31V20h4.69L12 23.31 15.31 20H20v-4.69zM12 18V6c3.31 0 6 2.69 6 6s-2.69 6-6 6z"></path></svg>` const lightIcon = `<svg fill="currentColor" aria-hidden="true" viewBox="0 0 24 24" tabindex="-1" title="Light"><path d="M20 8.69V4h-4.69L12 .69 8.69 4H4v4.69L.69 12 4 15.31V20h4.69L12 23.31 15.31 20H20v-4.69L23.31 12 20 8.69zM12 18c-3.31 0-6-2.69-6-6s2.69-6 6-6 6 2.69 6 6-2.69 6-6 6zm0-10c-2.21 0-4 1.79-4 4s1.79 4 4 4 4-1.79 4-4-1.79-4-4-4z"></path></svg>` // Content and click function for the theme picker themePicker.innerHTML = ` <div class="c-theme__grid"> ${darkIcon} ${sunsetIcon} ${sunriseIcon} ${lightIcon} </div> ` themePicker.onclick = () => { changeTheme(themes[count]) } document.getElementById('button').onclick = () => { changeTheme(themes[count]) } const capitalized = (word) => { return word.charAt(0).toUpperCase() + word.slice(1) } themes.forEach((theme, i) => { let box = document.createElement('button'); box.dataset.theme = theme box.onclick = () => { changeTheme(themes[i]) } box.classList = 'c-box'; box.style.setProperty('--bg', `var(--${theme}-bg)`); box.style.setProperty('--border', `var(--${theme}-border)`); box.style.setProperty('--surface', `var(--${theme}-surface)`); box.style.setProperty('--text-primary', `var(--${theme}-text-primary)`); box.style.setProperty('--text-secondary', `var(--${theme}-text-secondary)`); box.style.setProperty('--primary', `var(--${theme}-primary)`); box.style.setProperty('--text-inverse', `var(--${theme}-text-inverse)`); const iconRender = (theme) => { switch(theme) { case theme = 'dark': return darkIcon break; case theme = 'sunset': return sunsetIcon break; case theme = 'sunrise': return sunriseIcon break; case theme = 'light': return lightIcon break; } } box.innerHTML = ` <div class="c-box__title"> <span class="c-box__icon"> ${iconRender(theme)} </span> <label>${capitalized(theme)}</label> </div> <div class="c-box__swatches"> <span class="c-swatch" style="background: var(--bg)" title="bg"></span> <span class="c-swatch" style="background: var(--border)" title="border"></span> <span class="c-swatch" style="background: var(--surface)" title="surface"></span> <span class="c-swatch" style="background: var(--text-primary)" title="text-primary"></span> <span class="c-swatch" style="background: var(--text-secondary)" title="text-secondary"></span> <span class="c-swatch" style="background: var(--primary)" title="primary"></span> <span class="c-swatch" style="background: var(--text-inverse)" title="text-inverse"></span> </div> ` themeList.appendChild(box) }) changeTheme(themes[0])
That’s all! hopefully, you have successfully created theme switcher using CSS variables and JavaScript. If you have any questions or suggestions, feel free to comment below.
Proper asset protection strategies can help preserve family wealth while qualifying for Medicaid. Knowledgeable Medicaid planners provide strategic solutions.