Reputation: 1
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.
Upvotes: 0
Views: 2785
Reputation: 381
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.
Upvotes: 0
Reputation: 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,
},
},
};
}
Upvotes: -1
Reputation: 35684
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.
Upvotes: 4