0

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.

3 Answers 3

4

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 i.e. bg-primary and text-primary etc.

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks, I am trying to accomplish it using tailwind colors or at least maintaining the ability to add the number i.e. bg-primary-200. Seems that I'm best off adding the logic to Vue to switch between colors based on the value of myColor. Tailwind config is just a javascript file, perhaps there's another solution. Do you know of a way to change the value of the color based on a variable, perhaps like this? pastebin.com/HBqLuwGg
@TaylorFinklea Yes, the Tailwind config is essentially a JavaScript file. However, it remains inaccessible to your Vue app’s logic. This file operates solely within the Node.js runtime environment and is responsible for generating the required classes for your app during compile/build time. The solution above is the best if not the only solution that I can think of.
0

In addition to Daniel's answer, you can use tailwind's color variations. But you'll need to create those yourself.

This is how that would look in your tailwind config.

theme: {
  extend: {
    colors: {
      primary: {
        50: "var(--color-navbar-50)",
        100: "var(--color-navbar-100)",
        200: "var(--color-navbar-200)",
        300: "var(--color-navbar-300)",
        400: "var(--color-navbar-400)",
        500: "var(--color-navbar-500)",
        600: "var(--color-navbar-600)",
        700: "var(--color-navbar-700)",
        800: "var(--color-navbar-800)",
        900: "var(--color-navbar-900)",
        950: "var(--color-navbar-950)",
      },
    },
  },
}

And then you add each of those to the document's style property.

document.documentElement.style.setProperty("--color-primary-50", "#fef1fa");
document.documentElement.style.setProperty("--color-primary-100", "#fee5f7");
document.documentElement.style.setProperty("--color-primary-200", "#feccf1");
document.documentElement.style.setProperty("--color-primary-300", "#ffa2e5");
document.documentElement.style.setProperty("--color-primary-400", "#fd69d0");
document.documentElement.style.setProperty("--color-primary-500", "#f83cb9");
document.documentElement.style.setProperty("--color-primary-600", "#ea2ea2");
document.documentElement.style.setProperty("--color-primary-700", "#ca0c7c");
document.documentElement.style.setProperty("--color-primary-800", "#a70d66");
document.documentElement.style.setProperty("--color-primary-900", "#8b1056");
document.documentElement.style.setProperty("--color-primary-950", "#550231");

According to tailwind's documentation, the color palettes are manually created and there's no algorithm to generate custom palettes. There are multiple websites though that provide generators and apis such as this one https://www.tints.dev, that allow you to create a palette from a base color.

Daniel's answer is a good basis how to implement the CSS variables, but I would suggest to move the management itself out of the component and into a separate module.

Comments

-1

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

1 Comment

the tailwind colors and the classes are generated compile-time. This solution will not work. If you really want to use the tailwind color palette (with the numbers ie red-500) you will need to have the classes managed by vue (ie, color == 'blue' ? 'bg-blue-800 text-blue-300' : 'bg-green-800 text-green-300') this is going to be less "manageable" than using vars

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.