DEV Community

Cover image for Dark Mode Toggle for Vue.js Apps with Vuetify
H. Kamran
H. Kamran

Posted on • Originally published at hkamran.com on

Dark Mode Toggle for Vue.js Apps with Vuetify

Photo: Material.io

I use Vue.js and Vuetify for almost all of my websites and I’m a huge supporter of dark mode. One of the many reasons I chose Vuetify is because it has dark mode support out-of-the-box. So, without further ado, let me guide you through easily changing the dark mode state.

Setting the Default Dark Mode State

In order to set the default dark mode state, we have to open the plugin file for Vuetify, which is available at src/plugins/vuetify.js. By default, the file should look like the following.

import Vue from "vue";
import Vuetify from "vuetify/lib";

Vue.use(Vuetify);

export default new Vuetify({});
Enter fullscreen mode Exit fullscreen mode

To set the default state, we have to create a new object in the constructor called theme, and inside of that, set a variable called dark to true.

export default new Vuetify({
    theme: {
        dark: true
    }
});
Enter fullscreen mode Exit fullscreen mode

But if we want to change it from the user-facing interface, we have to use the variable provided by Vuetify.

Setting the Dark Mode State From the Interface

A copy of the final code is available at the bottom.

Before even adding the theme state-changing code, you have to decide where to put the code. You only have to put it in one location, preferably a location that is persistent, such as your App.vue or a component that is present on all pages, such as a navigation bar. With that decided, we can actually get to work.

In your file (I’m using a component that I’ve called NavigationBar), go to the script tag. There should be an export statement present. If not, go ahead and create it. The contents of the script tag should look similar to this:

export default {
    name: "NavigationBar"
}
Enter fullscreen mode Exit fullscreen mode

First, we need to add the method that will be called when the user clicks on a button. Underneath the name parameter, add a new object called methods.

export default {
    name: "NavigationBar",
    methods: {}
}
Enter fullscreen mode Exit fullscreen mode

I’m going to call my method toggleDarkMode, but feel free to call it whatever you’d like. This method is going to set the dark mode variable (this.$vuetify.theme.dark) to the inverse of what it is currently set to (if the theme is currently light, then this variable will be false), then set a local storage variable called darkTheme to the value of that variable.

methods: {
    toggleDarkMode: function() {
        this.$vuetify.theme.dark = !this.$vuetify.theme.dark;
        localStorage.setItem("darkTheme", this.$vuetify.theme.dark.toString());
    }
}
Enter fullscreen mode Exit fullscreen mode

With the function implemented, we now have to make it so that site will automatically pick up the theme state from the browser with the prefers-color-scheme CSS media query and/or the local storage state. The prefers-color-scheme state is set by your system.

To accomplish our task, we will use a Vue lifecycle hook called mounted which is called, as you may have guessed, when the component is mounted. We’ll add mounted() {} underneath the methods object.

export default {
    name: "NavigationBar",
    methods: { ... },
    mounted() {}
}
Enter fullscreen mode Exit fullscreen mode

We will first check what the value of our local storage variable is. If it exists, this.$vuetify.theme.dark is set to the value of the variable. If it doesn’t, we’ll check whether the user has dark mode enabled on their system, and set it to that.

mounted() {
    const theme = localStorage.getItem("darkTheme");

    // Check if the user has set the theme state before
    if (theme) {
        if (theme === "true") {
            this.$vuetify.theme.dark = true;
        } else {
            this.$vuetify.theme.dark = false;
        }
    } else if (
        window.matchMedia &&
        window.matchMedia("(prefers-color-scheme: dark)").matches
    ) {
        this.$vuetify.theme.dark = true;
        localStorage.setItem(
            "darkTheme",
            this.$vuetify.theme.dark.toString()
        );
    }
}
Enter fullscreen mode Exit fullscreen mode

All that’s left is to add a button to toggle the state. In the template tag, add the following:

<v-btn icon @click="toggleDarkMode">
    <v-icon>mdi-theme-light-dark</v-icon>
</v-btn>
Enter fullscreen mode Exit fullscreen mode

The code above is simple. It creates a Vuetify icon button, tells it to use the theme-light-dark icon from Material Design Icons and to add an event handler, which on click, calls the toggleDarkMode method.

That’s it. You’re finished! As I mentioned earlier, the final code is available on this GitHub Gist.

Thanks for reading!

Top comments (0)