Skip to content

Theme switch

A manual theme switch component for optional light or dark mode viewing.

Requirements (anchor)

Script (anchor)

The script needs to be loaded in the <head> prior to the CSS to negate the FOUC when changing or refreshing pages, you can include it as a linked file or within the document as preferred.

theme-switch.js

The script is also provided uncompressed in the js folder included with the StyleMods source files.

const storageKey = "theme-preference",

onClick = () => {
  (theme.value = "light" === theme.value ? "dark" : "light"), 
  setPreference();
},
  
getColorPreference = () => (localStorage.getItem(storageKey) 
  ? localStorage.getItem(storageKey) 
  : window.matchMedia("(prefers-color-scheme: dark)")
    .matches ? "dark" : "light"),
    
setPreference = () => {
  localStorage.setItem(storageKey, theme.value),
  reflectPreference();
},
  
reflectPreference = () => {
  document.firstElementChild.style.setProperty("color-scheme", theme.value);
},
  
theme = {
  value: getColorPreference()
};

reflectPreference(),

(window.onload = () => {
    reflectPreference(), 
    document.querySelector("#themes").addEventListener("click", onClick);
}),
  
window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change", ({matches: e}) => {
  (theme.value = e ? "dark" : "light"),
  setPreference();
});

It's been adapted from Adam Argyle's Building a theme switch component script to apply an inline color-scheme style attribute to the <html> tag as follows depending on the current color-scheme.

// If light
<html lang="en" style="color-scheme: light;">
// If dark
<html lang="en" style="color-scheme: dark;">

With no CSS provided for colors the default user-agent light and dark scheme color values will be used so the script isn't reliant on specific styling to work. It also respects a users preference for light or dark mode viewing so will even work if the button isn't included, and if the button's included it remembers the selection made and still respects user preferences.

Button (anchor)

A standard HTML button with the same ID attribute as below is all that's required for the switch.

<button id="themes">Theme switch</button>

With just the button and the script you have all the functionality required to manually switch between color-schemes and still respect a users viewing preferences.

Theme switch button (anchor)

The theme switch styles provide a simple sun and moon icon button using the attributes from the script and the button. The SVG variables and icon styles used replicate those included with the StyleMods icons and can be adapted with overrides to use icon tokens if also including the icons with your custom styles. See the source code below to view the styles.

The button is the same as the one above but uses a stylised <span> to hide the button text visually to ensure it meets basic HTML and content accessibility requirements. The span style is included with the theme switch styles at a high specificity so will only work within the button's ID and won't clash with other styles included for <span> elements.

<button id="themes"><span>Theme switch</span></button>

The styles don't include button property values so can style it as preferred. You can also customize the icon styles with overrides for the Sass variables in the source code below, see customizing for information on how to include them.

Using the module (anchor)

Load StyleMods as demonstrated (change file path as required) then include the Sass mixin anywhere below, and the script and button as described above:

custom.scss
@use "stylemods/scss" as *;
@include theme-switch-css;

See the using modules for information about how to compile the module in cascade layers.

Using the framework (anchor)

Using the recommended custom setup enable the styles in an overrides document:

overrides.scss
@use "stylemods/scss/configuration" as *;
$enable-theme-switch: true;

Include the overrides and the framework styles with your custom document for compiling the framework:

custom.scss
@use "overrides";
@use "stylemods/scss/stylemods";

See using the framework for more information.

Source code (anchor)

The Theme switch source file is included with the components module files, you can view the source code from the latest release (v1.5.0) via the Github link below.

Source documents
stylemods/scss/components/theme-switch.scss
stylemods/js/theme-switch.js
View on Github
https://github.com/pmbrown/StyleMods/blob/main/scss/components/theme-switch.scss
https://github.com/pmbrown/StyleMods/blob/main/js/theme-switch.js

Shared documentation about how to customize the default property values for the styles using the Sass and CSS variables is provided on the customizing page.