You can see a lot of examples with Dark & Light Toggle. But adding "system" or "auto" option along with that is bit tricky.
No time? Jump to the final code
Check out: Astroship - Free Astro Starter Template
System (Auto)
The system or auto option will switch the dark light theme based on user's system preferences. If they have "Auto" set in the system based on day/night, our site would show dark & light accordingly.
Step 1: Create the HTML
First, create themeswitch.astro
file in /components
folder. Then add the following HTML Code.
<select name="themeSwitch" id="themeSwitch">
<option value="system">System</option>
<option value="dark">Dark</option>
<option value="light">Light</option>
</select>
Step 2: Add the CSS
Now add a style to setup the color-scheme
for default HTML elements.
<style>
:global(.dark) {
color-scheme: dark;
}
</style>
Step 2: Add Script
Now, add the below javascript code to the file and it will handle all of the usecase for our theme switch.
<script>
const select = document.getElementById("themeSwitch") as HTMLSelectElement;
const theme = localStorage.getItem("theme");
const systemTheme = window.matchMedia("(prefers-color-scheme: dark)").matches
? "dark"
: "light";
if (theme !== null) {
select.value = theme;
} else {
select.value = systemTheme;
}
function updateTheme(value) {
const theme = value === "system" ? systemTheme : value;
document.documentElement.classList.remove("light", "dark");
document.documentElement.classList.add(theme);
localStorage.setItem("theme", value);
}
updateTheme(select.value);
select.addEventListener("change", (event: Event) => {
const select = event.target as HTMLSelectElement;
updateTheme(select.value);
});
</script>
That's it. You have a working Theme Switch in Astro.build.
Final Code
I have combined everything and added some styling with tailwindcss. Here's how the page would look finally.
---
import { Icon } from "astro-icon";
---
<div class="inline-flex items-center">
<Icon class="w-4 h-4 mr-2" name="heroicons-outline:sun" />
<select name="themeSwitch" id="themeSwitch">
<option value="system">System</option>
<option value="dark">Dark</option>
<option value="light">Light</option>
</select>
</div>
<style>
:global(.dark) {
color-scheme: dark;
}
</style>
<script>
const select = document.getElementById("themeSwitch") as HTMLSelectElement;
const theme = localStorage.getItem("theme");
const systemTheme = window.matchMedia("(prefers-color-scheme: dark)").matches
? "dark"
: "light";
if (theme !== null) {
select.value = theme;
} else {
select.value = systemTheme;
}
function updateTheme(value) {
const theme = value === "system" ? systemTheme : value;
document.documentElement.classList.remove("light", "dark");
document.documentElement.classList.add(theme);
localStorage.setItem("theme", value);
}
updateTheme(select.value);
select.addEventListener("change", (event: Event) => {
const select = event.target as HTMLSelectElement;
updateTheme(select.value);
});
</script>
Top comments (1)