loading...

Create Multiple Themes in Vue.js

khabz profile image Khabubu Ndivhuwo ・4 min read

We're in a golden era of JavaScript libraries and frameworks. This means things are constantly changing and frameworks are going in and out of vogue, but the core concepts of what we're trying to accomplish remain similar. Personally, my love for vue.js is growing day by day. So today I am going to build a simple Vue application with two themes. We can add dynamic theme in many ways. I’m going to share a simple method by creating two themes. By this method, you can add more themes.

Step 1: Create a Vue App

You have to install Vue-CLI on your machine. If you don’t have installed yet, then install:

npm install -g @vue/cli
# or
yarn global add @vue/cli

Now create a Vue application using this command & go to the directory:

# create app
vue create multiple-themes

# go to project dir
cd multiple-themes

Step 2: Install SASS/SCSS Pre-Processors

We’re going to write our styles in the SCSS file. We need to install the SCSS/SASS loader. Let’s install the pre-processors:

npm install -D sass-loader node-sass

In the root directory of your folder, create a file called webpack.config.js and paste this code:

module.exports = {
    module: {
        loaders: [
            {
                test: /\.vue$/,
                loader: 'vue'
            },
            {
                test: /\.s[a|c]ss$/,
                loader: 'style!css!sass'
            }
        ]
    },
    vue: {
        loaders: {
            scss: 'style!css!sass'
        }
    }
}

Step 3: The basic theme structure:

You can create your own custom theme

/*
* === COLORS ===
*/
:root {
    --app-background-color: #FFFFFF;
}

[theme="dark"] {
    --app-background-color: #091A28;
}

[theme="sepia"] {
    --app-background-color: #F1E7D0;
}

/*
* === STYLES ===
*/
.app-background {
  background-color: var(--app-background-color);
}

In the example, I’ve created 3 themes.

  1. :root is the default theme. We can call this light mode.
  2. [theme="dark"] is the theme named dark.
  3. [theme="sepia"] is the theme named sepia.

In this tutorial, I’m going to create two themes called light (:root default) and another is dark theme. Let’s create:
Navigate to src/assets folder and create a folder named css. Then go to the css folder and make two files called styles.scss and theme-colors.scss.

In the theme-colors.scss file, we'll keep colors and in the styles.scss file, we'll design.

Open the theme-colors.scss file and paste this code:

:root {
    --app-background-color: #FFFFFF;
    --dynamic-title-color: #363636;
    --dynamic-subtitle-color: #4a4a4a;
}

[theme="dark"] {
    --app-background-color: #091A28;
    --dynamic-title-color: #FFFFFF;
    --dynamic-subtitle-color: cyan;
}

Now open styles.scss. At first, we'll import the theme-colors.scss file in styles.css.

@import 'theme-colors';

/*
* === BODY, APP BACKGROUND ETC. ===
*/
html, body {
  height: 100%;
}

.container {
  max-width: 1040px;
}

.app-background {
  background-color: var(--app-background-color);
}

.dynamic-title {
  color: var(--dynamic-title-color);
}

.dynamic-subtitle {
  color: var(--dynamic-subtitle-color);
  padding-top: 10px;
}

The last thing, we need to import the CSS in the src/main.js file. Lets do this:

// custom styles
import './assets/css/styles.scss'

Step 4: Install a styling framework

I'm going to install Buefy (Lightweight UI components for Vue.js based on Bulma) to design our application. You can choose any styling framework like bootstrap. I decide to go with bulma.

# install
npm install buefy

# import to main.js
import Buefy from 'buefy'
import 'buefy/dist/buefy.css'

Vue.use(Buefy)

Step 5: Create Theme Switch & Store

I'm going to create a simple UI using Buefy in App.vue file. We’ll store selected theme in local using localStorage.

We'll take a checkbox for switching theme, will create a v-model to watch on switching. I hope you have the idea about data(), mounted() and watch.

Open App.vue file, and take a checkbox & create v-model named darkMode:

<input type="checkbox" class='theme-switch' v-model="darkMode"/>

To identify switch change, we need to add the watch method.

data() {
    return {
        darkMode: false,
    }
},
mounted() {
    // set 'app-background' class to body
    let bodyElement = document.body;
    bodyElement.classList.add("app-background");
},
watch: {
    darkMode: function () {
        // add/remove class to/from html tag
        let htmlElement = document.documentElement;

        if (this.darkMode) {
            localStorage.setItem("theme", 'dark');
            htmlElement.setAttribute('theme', 'dark');
        } else {
            localStorage.setItem("theme", 'light');
            htmlElement.setAttribute('theme', 'light');
        }
    }
}

Now on changing switch, the theme will change. We've stored the selected theme name in local storage. To display the selected theme, we need to set condition in mounted() method like this:

mounted() {
    // check for active theme
    let htmlElement = document.documentElement;
    let theme = localStorage.getItem("theme");

    if (theme === 'dark') {
        htmlElement.setAttribute('theme', 'dark')
        this.darkMode = true
    } else {
        htmlElement.setAttribute('theme', 'light');
        this.darkMode = false
    }
},

Step 6: Create Theme Switch & Store

Let's take a look at our App.vue

<template>
    <div id="app">
        <div class="section container">
            <div class="columns is-mobile">
                <div class="column is-2">
                    <a href="https://www.khabubundivhu.co.za" target="_blank">
                        <h1 v-if="darkMode ===true"  class="white-logo">Khabubu Ndivhu</h1>
                        <h1 v-else class="black-logo">Khabubu Ndivhu</h1>
                    </a>
                </div>
                <div class="column is-9">
                </div>
                <div class="column is-1">
                    <input type="checkbox" id='theme-switch' class='theme-switch' v-model="darkMode"/>
                    <label for='theme-switch'>
                        <span v-if="darkMode === true">
                            <img alt="logo" src="./assets/images/sun.png" width="40">
                        </span>
                        <span v-else>
                            <img alt="logo" src="./assets/images/moon.png" width="40">
                        </span>
                    </label>
                </div>
            </div>

            <section class="hero is-medium has-text-centered">
                <div class="hero-body">
                    <div class="container">
                        <h1 class="title dynamic-title">
                            <span v-if="darkMode === true">Dark Theme</span>
                            <span v-else>Light Theme</span>
                        </h1>
                        <h2 class="subtitle dynamic-subtitle">Create Multiple Themes in Vue.js</h2>
                    </div>
                </div>
            </section>

        </div>

    </div>
</template>

I did a lil something just to dynamically change my logo when I switch themes

<style scoped>
 .white-logo {
   color: white;
   font-weight: bold;
 }
 .black-logo {
   color: black;
   font-weight: bold;
 }
</style>

YAY!!!! Looks like we done. now let's run our application

npm run serve

Dark Theme

Alt Text

Light Theme

Alt Text

Thank you reading. You can checkout this tutorial code on this github repo

Posted on May 25 by:

khabz profile

Khabubu Ndivhuwo

@khabz

Full stack developer writing about things I wish I knew when I was learning how to code

Discussion

markdown guide