Dark Mode Toggle

MK

21 November 2021

5 min read

Tags

#Theming

#DarkMode

Important bits

Dark mode toggle without the flash of default theme:

  • CSS variables for color theming
  • Put data-theme attribute on <html>, not <body>, so we can run the JS before the DOM finishes rendering
  • Run local storage check in the <head>
  • JS for toggle button click handler can come after render

HTML

<!DOCTYPE html>
<html lang="en" data-theme="light">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
...
<script>
// If there's a theme stored in localStorage, use it on the <html>
const localStorageTheme = localStorage.getItem('theme');
if (localStorageTheme) {
document.documentElement.setAttribute(
'data-theme',
localStorageTheme
);
}
</script>
</head>
<body>
<div class="theme-toggle">
<button
class="theme-toggle-btn js-theme-toggle"
aria-label="Activate dark mode"
title="Activate dark mode"
>
<!--
<svg class="light-mode">
<use xlink:href="#sun"></use>
</svg>
<svg class="dark-mode">
<use xlink:href="#moon"></use>
</svg>
-->
</button>
</div>
<script src="app.js"></script>
</body>
</html>

CSS Variables

:root {
--bg: #ffffff;
--text: #000000;
}
[data-theme='dark'] {
--bg: #000000;
--text: #ffffff;
}

JavaScript

const themeToggleBtn = document.querySelector('.js-theme-toggle');
themeToggleBtn.addEventListener('click', () => onToggleClick());
const onToggleClick = () => {
const { theme } = document.documentElement.dataset;
const themeTo = theme && theme === 'light' ? 'dark' : 'light';
const label = `Activate ${theme} mode`;
document.documentElement.setAttribute('data-theme', themeTo);
localStorage.setItem('theme', themeTo);
themeToggleBtn.setAttribute('aria-label', label);
themeToggleBtn.setAttribute('title', label);
};

Resources

GET IN TOUCH

Contact

Want to reach out about a project, collaboration, or just want to say friendly hello?

Message not send