21 November 2021
•
5 min read
#Theming
#DarkMode
Dark mode toggle without the flash of default theme:
data-theme
attribute on <html>
, not <body>
, so we can run the JS before the DOM finishes rendering<head>
<!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>
:root { --bg: #ffffff; --text: #000000;}
[data-theme='dark'] { --bg: #000000; --text: #ffffff;}
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);};
Want to reach out about a project, collaboration, or just want to say friendly hello?