Dark Mode Toggle
A modified version of the bootstrap darkmode toggle script. This one adds a .dark-mode or .light-mode class to the html element instead of a data attribute, and can swap out images that have a prefers-color-scheme alternative. Any element with the class .theme-toggle can be used to swap modes with a click.
Snippet:
<script>
/*!
* Color mode toggler for Bootstrap's docs (https://getbootstrap.com/)
* Copyright 2011-2023 The Bootstrap Authors
* Licensed under the Creative Commons Attribution 3.0 Unported License.
* Modified by Tom Wilford 2024 to include:
* - Image Mode Switcher: https://michaelti.ca/sandbox/2020/05/01/dark-mode-images-with-a-manual-toggle-switch/
*/
(() => {
"use strict";
const getStoredTheme = () => localStorage.getItem("theme");
const setStoredTheme = (theme) => localStorage.setItem("theme", theme);
const getPreferredTheme = () => {
const storedTheme = getStoredTheme();
if (storedTheme) {
return storedTheme;
}
return window.matchMedia("(prefers-color-scheme: dark)").matches
? "dark"
: "light";
};
const setTheme = (theme) => {
if (
theme === "auto" &&
window.matchMedia("(prefers-color-scheme: dark)").matches
) {
document.documentElement.classList.add("dark-mode");
document.documentElement.classList.remove("light-mode");
} else {
const add = theme + '-mode';
const remove = theme === 'dark' ? 'light-mode' : 'dark-mode';
document.documentElement.classList.remove(remove);
document.documentElement.classList.add(add);
}
};
const setPictureTheme = (colorScheme) =>
{
document.querySelectorAll("picture > source[data-cloned-theme]").forEach((el) => {
el.remove();
});
if (colorScheme) {
document
.querySelectorAll(`picture > source[media*="(prefers-color-scheme: ${colorScheme})"]`)
.forEach((el) => {
const cloned = el.cloneNode();
cloned.removeAttribute("media");
cloned.setAttribute("data-cloned-theme", colorScheme);
el.parentNode.prepend(cloned);
});
}
};
setTheme(getPreferredTheme());
setPictureTheme(getPreferredTheme())
window
.matchMedia("(prefers-color-scheme: dark)")
.addEventListener("change", () => {
const storedTheme = getStoredTheme();
if (storedTheme !== "light" && storedTheme !== "dark") {
setTheme(getPreferredTheme());
setPictureTheme(getPreferredTheme())
}
});
window.addEventListener("DOMContentLoaded", () => {
setPictureTheme(getPreferredTheme())
document.querySelectorAll(".theme-toggle").forEach((toggle) => {
toggle.addEventListener("click", () => {
const theme = getPreferredTheme() === 'dark' ? 'light' : 'dark';
setStoredTheme(theme);
setTheme(theme);
setPictureTheme(theme)
});
});
});
})();
</script>