Skip to content

Commit bb81446

Browse files
committed
add support for light and dark mode based on system preferences
1 parent c6525ca commit bb81446

1 file changed

Lines changed: 29 additions & 12 deletions

File tree

‎_layouts/default.html‎

Lines changed: 29 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,11 @@
22
<html lang="en">
33
<head>
44
<meta charset="utf-8">
5-
<!-- Theme: apply saved preference immediately to avoid flash of wrong theme -->
5+
<!-- Theme: apply system preference immediately to avoid flash of wrong theme -->
66
<script>
77
try {
8-
var savedTheme = localStorage.getItem('theme-preference');
9-
if (savedTheme === 'dark') document.documentElement.setAttribute('data-theme', 'dark');
10-
else if (savedTheme === 'light') document.documentElement.setAttribute('data-theme', 'light');
8+
var initialTheme = (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) ? 'dark' : 'light';
9+
document.documentElement.setAttribute('data-theme', initialTheme);
1110
} catch(e) {}
1211
</script>
1312
<title>{% if page.title %}{{ page.title }} – {% endif %}{{ site.name }} – {{ site.description }}</title>
@@ -151,6 +150,7 @@ <h1 class="site-name">{{ site.name }}</h1>
151150
<script>
152151
(function() {
153152
var STORAGE_KEY = 'theme-preference';
153+
var prefersDarkQuery = window.matchMedia ? window.matchMedia('(prefers-color-scheme: dark)') : null;
154154

155155
var ICONS = {
156156
light: '<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="5"/><line x1="12" y1="1" x2="12" y2="3"/><line x1="12" y1="21" x2="12" y2="23"/><line x1="4.22" y1="4.22" x2="5.64" y2="5.64"/><line x1="18.36" y1="18.36" x2="19.78" y2="19.78"/><line x1="1" y1="12" x2="3" y2="12"/><line x1="21" y1="12" x2="23" y2="12"/><line x1="4.22" y1="19.78" x2="5.64" y2="18.36"/><line x1="18.36" y1="5.64" x2="19.78" y2="4.22"/></svg>',
@@ -161,14 +161,20 @@ <h1 class="site-name">{{ site.name }}</h1>
161161
try { return localStorage.getItem(STORAGE_KEY); } catch(e) { return null; }
162162
}
163163

164+
function getSystemTheme() {
165+
return (prefersDarkQuery && prefersDarkQuery.matches) ? 'dark' : 'light';
166+
}
167+
164168
function getEffectiveTheme() {
165169
var stored = getStoredTheme();
166170
if (stored === 'dark' || stored === 'light') return stored;
167-
return (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) ? 'dark' : 'light';
171+
return getSystemTheme();
168172
}
169173

170-
function applyTheme(theme) {
171-
try { localStorage.setItem(STORAGE_KEY, theme); } catch(e) {}
174+
function applyTheme(theme, persist) {
175+
if (persist) {
176+
try { localStorage.setItem(STORAGE_KEY, theme); } catch(e) {}
177+
}
172178
document.documentElement.setAttribute('data-theme', theme);
173179
updateButton(theme);
174180
document.dispatchEvent(new CustomEvent('themechange'));
@@ -184,21 +190,32 @@ <h1 class="site-name">{{ site.name }}</h1>
184190
}
185191

186192
document.addEventListener('DOMContentLoaded', function() {
187-
// Migrate any legacy 'system' value
193+
// Migrate all existing saved values to system-follow behavior.
188194
var stored = getStoredTheme();
189-
if (stored && stored !== 'light' && stored !== 'dark') {
195+
if (stored) {
190196
try { localStorage.removeItem(STORAGE_KEY); } catch(e) {}
191-
document.documentElement.removeAttribute('data-theme');
192197
}
193198

194-
updateButton(getEffectiveTheme());
199+
applyTheme(getSystemTheme(), false);
195200

196201
var btn = document.getElementById('theme-toggle');
197202
if (btn) {
198203
btn.addEventListener('click', function() {
199-
applyTheme(getEffectiveTheme() === 'dark' ? 'light' : 'dark');
204+
applyTheme(getEffectiveTheme() === 'dark' ? 'light' : 'dark', false);
200205
});
201206
}
207+
208+
if (prefersDarkQuery) {
209+
var handleSystemThemeChange = function() {
210+
applyTheme(getSystemTheme(), false);
211+
};
212+
213+
if (typeof prefersDarkQuery.addEventListener === 'function') {
214+
prefersDarkQuery.addEventListener('change', handleSystemThemeChange);
215+
} else if (typeof prefersDarkQuery.addListener === 'function') {
216+
prefersDarkQuery.addListener(handleSystemThemeChange);
217+
}
218+
}
202219
});
203220
})();
204221
</script>

0 commit comments

Comments
 (0)