1

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>
4

5 Answers 5

6

Is it advised to utilise a dynamic class in a tailwind?

Ans: No

The usage of dynamic classes in tailwind-css is often not advised since tailwind employs tree-shaking, which means that any class that wasn't specified in your source files won't be created in the output file. It is thus advised to use complete class names

According to Docs

If you use string interpolation or concatenate partial class names together, Tailwind will not find them and therefore will not generate the corresponding CSS

Is there work around ?

Ans: Yes, use Safelisting classes in your tailwind.config.cs

Safelisting is a last-resort, and should only be used in situations where it’s impossible to scan certain content for class names. These situations are rare, and you should almost never need this feature.


Particular to you, you want to have 100 500 700 shades of colors. You can use regular expressions to include all the colors you want using pattern and specify the shades accordingly .

Note: You can force Tailwind to create variants as well:

In tailwind.config.js

module.exports = {
  content: [
    './pages/**/*.{html,js}',
    './components/**/*.{html,js}',
  ],
  safelist: [
    {
      pattern: /bg-(red|green|blue|orange)-(100|500|700)/, // You can display all the colors that you need
      variants: ['lg', 'hover', 'focus', 'lg:hover'],      // Optional
    },
  ],
  // ...
}

To include all the bg-colors, you can use the following code:

module.exports = {
  content: [
     ...
  ],
  safelist: [
    {
      pattern: /bg-+/, // 👈  This includes bg of all colors and shades
    },
  ],
  ...
}

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

Comments

3

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.

1 Comment

It can be done even this way , which is by using temporary hardcoded values, I have tried to provide generic answer for all use case. You might want to check that out !!
2

The method I always use is to simply put in all the possible classes inside the file when dealing with some basic dynamic classes. I noticed that even if the classes are specified in commented lines, Tailwind CSS still imports the styling of those classes when found inside any file.

Here's an example:

<template>
    <div :class="`bg-${color}-100 border-${color}-500 text-${color}-700`" class="border-l-4 p-4" role="alert">
        test
    </div>
</template>
<script>
    /* All supported classes for color props
    bg-red-100 border-red-500 text-red-700
    bg-orange-100 border-orange-500 text-orange-700
    bg-green-100 border-green-500 text-green-700
    bg-blue-100 border-blue-500 text-blue-700
    */
    export default {
        name: 'Alert',
        props: {
            color: {type: String, default: 'red'}
        }
    }
</script>

So now all these would work fine:

<Alert color="red"></Alert>
<Alert color="orange"></Alert>
<Alert color="green"></Alert>
<Alert color="blue"></Alert>

But this one won’t have any styling as the generated classes for purple are not prespecified in any files:

<Alert color="purple"></Alert>

Comments

0

TailwindCSS now using tree-shaking to generate the class (To reduce importing redundant css class). Solution: You should use Safelisting classes to ensure it's generated before.

https://tailwindcss.com/docs/content-configuration#safelisting-classes

You can config in file tailwind.config.js in root. In your case, you can create safe-list for background color, text color, border color, ...

module.exports = {
    //Rest of config goes here ...
    safelist: [
        {
            pattern: /(from|via|to|border|bg|text)-(.*)-(\d{1}0{1,2})/,
            variants: [
                "hover",
                "active",
                "focus",
                "visited",
                "focus-visible",
                // It is recommended you comment out the items below this one and only uncomment them as needed
                // Leaving all of these here causes hot reload to become extremely laggy
                "first",
                "last",
                "odd",
                "even",
                "focus-within",
                "target",
                "only",
                "first-of-type",
                "last-of-type",
                "only-of-type",
                "empty",
                "disabled",
                "checked",
                "indeterminate",
                "default",
                "required",
                "valid",
                "invalid",
                "in-range",
                "out-of-range",
                "placeholder-shown",
                "autofill",
                "read-only",
            ],
        },
    ],
};

Comments

0

I found this is the best option if you need to do this with a custom hex code.

<template>
  <div :style="gradientBackground" class="other-tailwind-classes">
    <p>Things</p>
  </div>
</template>

<script setup>
const props = defineProps({
  item: {
    type: Object,
    required: true,
  },
})

const gradientBackground = computed(() => {
  return `background-image: linear-gradient(to right, #${props.item.bg_color_left}, #${props.item.bg_color_right})`
})
</script>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.