0

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>
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
SymmetricsWeb
  • 586
  • 6
  • 20
  • Try using `bg-[${this.color}]` where `this.color` is `hex` color like #efefef. – Matias Bertoni Dec 30 '22 at 01:54
  • 1
    There are many answers for this question regarding dynamic classes in Tailwind, see the following: https://stackoverflow.com/questions/69687530/dynamically-build-classnames-in-tailwindcss https://stackoverflow.com/questions/71063619/react-and-tailwind-css-dynamically-generated-classes-are-not-being-applied https://stackoverflow.com/questions/67212731/dynamically-created-classes-not-available-when-using-nuxt-build-tailwindcss or either search for `dynamic classes in tailwind-css`. – ChenBr Dec 30 '22 at 11:08
  • Does this answer your question? [React and Tailwind CSS: dynamically generated classes are not being applied](https://stackoverflow.com/questions/71063619/react-and-tailwind-css-dynamically-generated-classes-are-not-being-applied) – ChenBr Dec 30 '22 at 11:08
  • Does this answer your question? [Conditionally set background color in React component with Tailwind CSS](https://stackoverflow.com/questions/71413730/conditionally-set-background-color-in-react-component-with-tailwind-css) – Ihar Aliakseyenka Dec 30 '22 at 14:28

4 Answers4

2

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.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
SymmetricsWeb
  • 586
  • 6
  • 20
  • 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 !! – krishnaacharyaa Dec 30 '22 at 03:16
2

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
    },
  ],
  ...
}

krishnaacharyaa
  • 14,953
  • 4
  • 49
  • 88
1

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>
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
silver
  • 4,433
  • 1
  • 18
  • 30
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",
            ],
        },
    ],
};
KitKit
  • 8,549
  • 12
  • 56
  • 82