Home > database >  Dynanically change tailwindcss color based on user input in Vue3/Nuxt3
Dynanically change tailwindcss color based on user input in Vue3/Nuxt3

Time:02-03

I am trying to build a way for a user to define the primary color of the website. When defining my tailwind classes, I want to use something like bg-primary-600 rather than hard coding a color, so that when the value for primary changes, it will update the style.

Here I have my test environment: https://stackblitz.com/edit/nuxt-starter-qinx8e?file=tailwind.config.js

For those who don't want to open the link

tailwind.config.js

/** @type {import('tailwindcss').Config} */
const colors = require('tailwindcss/colors');

module.exports = {
  darkMode: 'class',
  content: [
    './components/**/*.{js,vue,ts}',
    './layouts/**/*.vue',
    './pages/**/*.vue',
    './plugins/**/*.{js,ts}',
    './nuxt.config.{js,ts}',
    './app.vue',
  ],
  theme: {
    extend: {
      colors: {
        // This should be changed by the user instead of hard coding
        primary: colors.blue,
      },
    },
  },
};

app.vue

<template>
  <div>
    <div >HELLO WORLD</div>
    <div >HELLO WORLD</div>
    <button  @click="myColor = 'blue'">
      Blue
    </button>
    <button  @click="myColor = 'green'">
      Green
    </button>
    <body >
      My color is: {{ myColor }}
    </body>
  </div>
</template>

<script setup>
const myColor = ref('orange');
</script>

I cannot seem to figure out how to dynamically change the color in Tailwind. I'm able to hard code a value like in my example, but I cannot assign this value to a reactive variable and have it update.

I cannot figure out how to make the myColor ref update the color in tailwind. Note that I don't want to update it just in the page, I need to be able to update tailwind so that any reference to primary, regardless of the page or component will have the correct color.

CodePudding user response:

You can use CSS variables to achieve that

In your tailwind config, set primary as a CSS var:

  theme: {
    extend: {
      colors: {
        // This should be changed by the user instead of hard coding
        primary: 'var(--color-primary)',
        // This will extend functionality of your color
        // so you can use opacity on it like text-secondary/80
        // var has to have rgb in it not hex color like: --color-info: 14 165 233;
        secondary: 'rgb(var(--color-secondary) / <alpha-value>)'
      },
    },
  },

Then you can override the var in the app using style.setProperty:

<template>
  <div>
    <div >HELLO WORLD</div>
    <button  @click="myColor = 'blue'">
      Blue
    </button>
    <button  @click="myColor = 'green'">
      Blue
    </button>
    <body >
      My color is: {{ myColor }}
    </body>
  </div>
</template>

<script setup>
import { ref, watch } from 'vue';
const colors = {
  blue: '#0077FF',
  green: '#00DD77',
};
const myColor = ref('orange');
watch(myColor, (color) => {
  document.documentElement.style.setProperty('--color-primary', colors[color]);
});
</script>

<style>
:root {
  --color-primary: #ff9900;
}
</style>

Note that tailwind will not be able to determine the color variations, so you cannot use bg-primary-500 or bg-primary-200 you need to drop the number i.e. bg-primary and text-primary etc.

CodePudding user response:

I figured out how to dynamically set the primary color and still maintain the ability to do things like bg-primary-600. Now I just need to figure out how to make the user able to change this value, but that's a cookie issue not a tailwindcss issue.

I split up the export into separate blocks, so that I could dynamically define my theme block based on the value of a variable.

tailwind.config.js

/** @type {import('tailwindcss').Config} */
const colors = require('tailwindcss/colors');
const color = 'blue';

exports.darkMode = 'class';

exports.content = [
  './components/**/*.{js,vue,ts}',
  './layouts/**/*.vue',
  './pages/**/*.vue',
  './plugins/**/*.{js,ts}',
  './nuxt.config.{js,ts}',
  './app.vue',
];

if (color === 'blue') {
  exports.theme = {
    extend: {
      colors: {
        primary: colors.blue,
      },
    },
  };
}
if (color === 'green') {
  exports.theme = {
    extend: {
      colors: {
        primary: colors.green,
      },
    },
  };
}
if (color === 'orange') {
  exports.theme = {
    extend: {
      colors: {
        primary: colors.orange,
      },
    },
  };
}
  • Related