Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Best way to dynamically change theme of my Vue.js SPA?

So I think the title is enough explaination: I would like to dynamically theme my whole application. Maybe this means to change color of all divs when I press a specific button, or change the whole webapp's colors when a specific user logs in.

Just to give some insights on what I am currently working on I will say that I have built a Vue.js app that uses many libraries, including one called Element-ui which already has a theming option built onto it. The problem is that it's written in scss and I would like to change all the variable colors during the navigation. My project looks something like this:

<template>
  ... some HTML and components...
</template>

<script>
  ... some javascript ...
</script>

<style scoped>
  ... some style that is scoped to the current component only ...
</style>

I have many files like this one so making a "global function" for all of them doesn't seem practical to me. Also I import the main scss file just once in my main.js.

Is there anything I can do to create a dinamic theming for my webapp? Is using saas a good idea? Javascript maybe?

EDIT

I feel like I didn't explain it good enough so I want to add a simple example. If you visit the Element page you can see in the top right corner there is a color selector that, when a color changes, it changes also the whole website's accent colors like the buttons colors, the links colors etc.

Hope this can help understanding a bit better

EDIT

Right now I have settled on a very poor and, I think, badly optimized solution. The idea is that when the user changes theme, I just create a new css file and append it to the current document.

let sheet = document.createElement('style')
sheet.innerHTML = `*[class*="--primary"]{
                      background-color: ${colors[0]};
                    }
                    ...`;
document.body.appendChild(sheet);

I truly think this is a very bad solution but right now I can't come up with nothing else that could work dinamically when the user changes a parameter. I would really want the process to be flawless: the user picks a color and the whole application just changes to that specific color, no prebuilt theme.css.

FINAL EDIT

I've finally found a solution, refer to the answer!

like image 237
Eugenio Avatar asked Mar 29 '18 08:03

Eugenio


1 Answers

Finally, after a few long days I came up with a solution that I think is both easy to implement and very very lightweight.

CSS VARIABLES

Before searching up a lot, I didn't even know the existance of these kind of variables and they don't seem so used. Anyway, I hope this can help someone out there seeking my same answer:

<template
  <app-main></app-main>
  <app-sidebar></app-sidebar>
  ...
</template>

<style>
  :root{
    --primary-color: #C5C5C5!important;
    --secondary-color: #6C7478!important;
    --tertiary-color: #FFFFFF!important;
    --success-color: #80b855!important;
    --warning-color: #eaca44!important;
    --error-color: #ef4d4d!important;
  }

  /* Theming */
  header{
    background-color: var(--primary-color);
  }
  div{
    color: var(--tetriary-colory);
  }
  ...
  /*   END   */
</style>

<script>
  import axios from 'axios' /* all your imports etc. */

  export default{
    data(){
    },
    methods: {
      axios.post(`http://localhost:8080/foo`).then(function (response){
        let bodyStyles = document.body.style;
        bodyStyles.setProperty('--primary-color', response.colors[0]);
        bodyStyles.setProperty('--tertiary-color', response.colors[1]);
        ...
      }
    }
  }
</script>

As you can see, I just initialize a few useful CSS variables and when I need them (for example in that api post call) I just modify them using a simple bodyStyles.setProperty('propertyName') function.

I really enjoy this type of setup since I use it in my login page so when a user successfully logs-in I load from the database his own colors and set them up just like that.

My website example

Hoping this can help someone! Cheers!

like image 120
Eugenio Avatar answered Nov 25 '22 23:11

Eugenio