Skip to content

Instantly share code, notes, and snippets.

@topdown
Created April 29, 2025 23:43
Show Gist options
  • Save topdown/b4aaf47a3c19d173a9a08a1a8e3138ae to your computer and use it in GitHub Desktop.
Save topdown/b4aaf47a3c19d173a9a08a1a8e3138ae to your computer and use it in GitHub Desktop.
Light / Dark mode
<!doctype html>
<html lang="en" class="light">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Document</title>
<style>
:root {
--body-background: #fff;
color: #000;
}
html.dark {
--body-background: #000;
color: #fff;
}
html.dark #color_scheme_toggle {
background-color: #fff;
color: #000;
}
html.dark a .icon-sun {
color: #fff;
}
html.light #color_scheme_toggle {
background-color: #000;
color: #fff;
}
html.light a .icon-moon {
color: #000;
}
#color_scheme_toggle {
position: fixed;
bottom: 10px;
right: 10px;
background: none;
border: none;
cursor: pointer;
width: 32px;
height: 32px;
border-radius: 50%;
z-index: 9999;
text-align: center;
vertical-align: middle;
display: flex;
justify-content: center;
align-items: center;
padding: 4px;
}
.icon-sun, .icon-moon {
cursor: pointer;
transition: transform 0.3s ease;
}
body {
background-color: var(--body-background);
}
</style>
</head>
<body>
<main>
<h1>Test</h1>
<h2>Dark / Light mode</h2>
</main>
<a href="javascript:void(0)" id="color_scheme_toggle">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" stroke="currentColor" stroke-width="2"
stroke-linecap="round" stroke-linejoin="round" class="icon-sun">
<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>
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" stroke="currentColor" stroke-width="2"
stroke-linecap="round" stroke-linejoin="round" class="icon-moon">
<path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z" />
</svg>
</a>
<script>
const CookieManager = {
set: (key, value, days = 365, path = '/') => {
const expires = new Date(Date.now() + days * 864e5).toUTCString();
document.cookie = `${encodeURIComponent(key)}=${encodeURIComponent(value)}; expires=${expires}; path=${path}`;
},
get: (key) => {
return document.cookie
.split('; ')
.find(row => row.startsWith(encodeURIComponent(key) + '='))
?.split('=')[1] || null;
},
delete: (key, path = '/') => {
document.cookie = `${encodeURIComponent(key)}=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=${path}`;
}
};
const html_tag = document.querySelector('html');
const icon_sun = document.querySelector('.icon-sun');
const icon_moon = document.querySelector('.icon-moon');
// Remove existing theme classes
function setTheme(mode) {
html_tag.classList.remove('dark', 'light');
html_tag.classList.add(mode);
if (mode === 'dark') {
icon_moon.style.display = 'block';
icon_sun.style.display = 'none';
} else {
icon_sun.style.display = 'block';
icon_moon.style.display = 'none';
}
}
// Get and apply theme
let theme = CookieManager.get('color_scheme');
if (theme === 'dark' || theme === 'light') {
setTheme(theme);
} else {
// Fallback to browser preference
const prefers_dark = window.matchMedia('(prefers-color-scheme: dark)').matches;
theme = prefers_dark ? 'dark' : 'light';
setTheme(theme);
CookieManager.set('color_scheme', theme); // Save it for next time
}
// Toggle theme
document.querySelector('#color_scheme_toggle').addEventListener('click', () => {
const current = html_tag.classList.contains('dark') ? 'dark' : 'light';
const next = current === 'dark' ? 'light' : 'dark';
setTheme(next);
CookieManager.set('color_scheme', next);
});
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment