Making a Vuejs dark theme toggle
Making a dark theme with CSS variables and @media
If you haven't read my previous article on making a dark theme with CSS variables. Check it out before reading this because this is a continuation of that article.
The first called script
This script should be called as soon as possible so that the proper CSS can be applied to the document. If you are using Gridsome, you can add this script to your index.html
file. This code checks for the color of the device and then set a local storage variable and a data attribute to the theme name. For example, if the device's color scheme was set to 'dark mode' the local storage variable and data attribute would be set to dark
.
Setting a data attribute makes it possible to change the CSS based on the color scheme.
(function() {
try {
// Checks for the color scheme of the device.
// In this case it checks for anything that is not light theme.
var media = window.matchMedia("not all and (prefers-color-scheme: light)"),
body = document.body;
if (localStorage.getItem("theme") == "dark") {
body.setAttribute("data-theme", "dark");
} else if (localStorage.getItem("theme") == "light") {
body.setAttribute("data-theme", "light");
} else if (media.matches) {
body.setAttribute("data-theme", "dark");
localStorage.setItem("theme", "dark");
}
media.addListener(function() {
if (media.matches) {
body.setAttribute("data-theme", "dark");
localStorage.setItem("theme", "dark");
} else {
body.setAttribute("data-theme", "light");
localStorage.setItem("theme", "light");
}
});
} catch (err) {}
})();
Theme Toggle Component
In the navigation, I have made a button component to toggle the theme. This is the HTML for that component.
<template>
<button
:title="theme == 'dark' ? 'Dark Theme' : 'Light Theme'"
@click="toggleTheme()"
class="theme"
>
<Moon :is="theme == 'dark' ? 'Moon' : 'Sun'" height="20px" />
</button>
</template>
<script>
import Moon from "~/assets/images/moon-regular.svg";
import Sun from "~/assets/images/sun-regular.svg";
export default {
components: {
Moon,
Sun
},
data() {
return {
theme: localStorage.getItem("theme")
};
},
methods: {
toggleTheme() {
if (this.theme == "dark") {
this.theme = "light";
document.body.setAttribute("data-theme", "light");
localStorage.setItem("theme", "light");
} else {
this.theme = "dark";
document.body.setAttribute("data-theme", "dark");
localStorage.setItem("theme", "dark");
}
}
}
};
</script>
If you would like to see this code in action check out the navigation on Developer Bacon.