Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

richardhulbert's avatar

Vue 3 and Tailwind computed properties

In the past I have used the excellent bootstrap-vue component set but hey if you are using Jetstream or Breeze with Intetia there is no bootstrap option. You have and use Tailwind and we all know that Tailwind and Bootstrap don't play well together. So I am building out a library of Vue 3 components.

Tailwind is great but there are some weaknesses. Let's take for example a button that might be used in various places through the application.

<template>
  <button  class="bg-slate-500 hover:bg-slate-700 transition-colors ease-in text-white font-bold py-2 px-4 rounded font-light"><slot></slot></button>
</template>

you might use it like this

    <tw-button @click="createProducts" >Create</tw-button>

and you could override the background color by doing this:

    <tw-button @click="createProducts" class="bg-indigo-500" >Create</tw-button>

That would work BUT what happens when someone (the client) says - "you know what I think the buttons should be green".

If you have lots of buttons that might need a real pain to find even with a fancy IDE like phpStorm.

One partial workaround would be to create a color alias in tailwind.config.js

const colors = require('tailwindcss/colors')
...
theme: {
    extend: {
      colors:{
        primary:colors.cyan,
        secondary:colors.lime
      }
    },
  },
...

One could then code the button like this:

    <tw-button @click="createProducts" class="bg-primary-500" >Create</tw-button>

Now if you want to change the color globally you can do it in the tailwind.config.js file.

Frustratingly what you cannot do is something like this in your component:

<template>
  <button :class="bgcolor" class="hover:bg-slate-700 transition-colors ease-in text-white font-bold py-2 px-4 rounded font-light"><slot></slot></button>
</template>

<script>
export default {
  props: {
    color: {
      type: String,
      default: 'slate'
    }
  },
  computed: {
    bgcolor() {
      return 'bg-'+this.color+'-500'
    }
  },


}
</script>

I think that this is because Tailwind strips out all the classes it can't find in the files using preg match but for what ever reason it is a quite pain. I can't be the only disappointed user. Does anyone know of a good solution to creating dynamic tailwind classes that?

0 likes
10 replies
richardhulbert's avatar

@Sinnbeck Thanks Sinnbeck for your (usual speedy and accurate) reply. Yes safe listing classes does work (as does hiding the classes in the app somewhere). However as you can imagine to make this genuinely useful I would not just have to safelist all the bg- classes but also border- text- etc etc.

As a starting point

 safelist: [
    {
      pattern: /bg-(\w+)-(\d00)/,
    },
    {
      pattern: /border-(\w+)-(\d00)/,
    },
    {
      pattern: /text-(\w+)-(\d00)/,
    },
  ],

obviously these can be amended to something more specific (and therefore result is a smaller css output)

pattern: /bg-(primary|secondary|blue)-(100|200|300)/,

For a user using a component library it might be a bit of an ask to have to get involved in editing the tailwind.config.js but at the moment I guess that this is the best compromise.

Sinnbeck's avatar

@richardhulbert yeah the problem is that whole point of tailwind is to make the css file as small as possible. Without any cleanup (tailwind v1) the css file would grow to like 3-4mb. I personally prefer to not pass the colors but rather make a lookup map in the component. So if I pass "error", that component grabs the red colors

const lookup ={
     error: 'text-red-200 bg-red-800',
     success: 'text-green-200 bg-green-800',
}

But setting up custom names might be better in your case

richardhulbert's avatar

@Sinnbeck I am thinking with a reusable component hat on. A programmer wants to pull in say a button and set the general colour (the button could be an outline style for instance) - perhaps if they are savvy they will create a colour alias such as primary in the 'tailwind.config.js' file and then really they can tune the safelist after the client has changed their mind about border and background colours fifty times 🤪.

Ultimately what would be great is that the purging takes place after the vue app has been compiled maybe some sort of routine that gets all classes in the output and that form the basis for the purge. Anyhow thanks for your thoughts

Sinnbeck's avatar

@richardhulbert but the class strings would still be concatenated by the browser, not the compiler?

But I get the problem. I only create components for my own projects.

Maybe it would be worth checking how daisyui does it https://daisyui.com/ I believe they use semantic naming for colors, but I'm unsure how the developer specifies them

richardhulbert's avatar

@Sinnbeck Hi and thanks. Yes I worked out that one can do this and indeed for buttons it makes sense. I have made a start on some reusable components and as you can see the project points people to the primary / secondary concept. I would be very grateful if you gave it the once over and told me whether it is worth continuing with. have a look https://github.com/richardhulbert/vue3-tailwind-components

Sinnbeck's avatar

@richardhulbert A great start. Personally I would probably go with suggesting the primary/secondary approach first. Maybe make a list of colors that you always include or something like that :)

richardhulbert's avatar

@sinnbeck I have taken your advice and standardised the colours 'a la bootstrap' I have added some more components and discovered an important configuration option needed in tailwind.config.js

For those following along please do have a look and try it out. npm i vue3-tailwind-components

Please or to participate in this conversation.