简体   繁体   中英

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

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 class="bg-red-600 h-16 mb-4">HELLO WORLD</div>
    <div class="bg-primary-600 h-16 mb-4">HELLO WORLD</div>
    <button class="bg-blue-200 rounded-lg p-4 mx-2" @click="myColor = 'blue'">
      Blue
    </button>
    <button class="bg-green-200 rounded-lg p-4" @click="myColor = 'green'">
      Green
    </button>
    <body class="mx-2">
      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.

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 class="bg-primary h-16 mb-4">HELLO WORLD</div>
    <button class="bg-blue-200 rounded-lg p-4 mx-2" @click="myColor = 'blue'">
      Blue
    </button>
    <button class="bg-green-200 rounded-lg p-4" @click="myColor = 'green'">
      Blue
    </button>
    <body class="mx-2">
      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 ie bg-primary and text-primary etc.

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,
      },
    },
  };
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM