Search code examples
vue.jsvuejs3tailwind-cssvite

Tailwind CSS color is not working on dynamic classes. Vue.js + Vite


It is the first time I’m using Tailwind CSS, and I can't figure out why colors are not working. This is a fresh install of Laravel Jetstream which comes with Tailwind CSS, Vue.js 3, Vite, and Inertia.

It seems like the relevant styling is not imported from Tailwind CSS if classes are added dynamically.

Here's some basic component:

<template>
    <div :class="style" class="border-l-4 p-4" role="alert">
        <p><slot name="headline"></slot></p>
        <p class="pt-3" v-if="slots.error"><span class="font-bold">Message:</span><slot name="error"></slot></p>
        <div class="my-3" v-if="slots.info"><slot name="info"></slot></div>
    </div>
</template>
<script setup>
    import { useSlots } from 'vue'
    const slots = useSlots()
</script>
<script>
export default {
    name: 'Alert',
    props: {
        color: {type: String, default: 'red'}
    },
    computed: {
        style() {
            return `bg-${this.color}-100 border-${this.color}-500 text-${this.color}-700`
        }
    }

}
</script>

And using something like this does not have any color related styling although the class is there:

<Alert color="orange" class="my-5">
    <template #headline>Test</template>
</Alert>

But if the dynamic classes are also specified somewhere in the same page then everything works.

I.e.,

<div class="bg-orange-100 border-orange-500 text-orange-700"></div>
<Alert color="orange" class="my-5">
        <template #headline>Test</template>
</Alert>

Solution

  • This was relatively easily fixed. It was mentioned in Dynamic class names to avoid constructing class name dynamically.

    So, in the computed style, I just specify the full class name conditionally with all the possible values.

    It was changed from

    style() {
        return `bg-${this.color}-100 border-${this.color}-500 text-${this.color}-700`
    }
    

    to this:

    style() {
        const styles = {
            default : 'bg-cyan-100 border-cyan-500 text-cyan-700',
            red : 'bg-red-100 border-red-500 text-red-700',
            orange: 'bg-orange-100 border-orange-500 text-orange-700',
            green: 'bg-green-100 border-green-500 text-green-700',
            blue: 'bg-blue-100 border-blue-500 text-blue-700',
        }
        return styles[this.color] ?? styles.default
    }
    

    Now everything works perfectly.