Search code examples
vuejs3tailwind-css

Any solution for Tailwind colors not generated properly with a dynamic class in Vue?


computed: {
    background() {
      switch (this.color) {
        case "blue-500":
          return "bg-blue-500" // this working
        case "orange-600":
          return "bg-orange-500"
          default:
          return `bg-${this.color}` // but not this, only work if cached
      }
    }

I'm implementing it with something like this

<template>
  <div :class="`fixed p-1 px-4 right-1/2 translate-x-1/2 shadow-xl rounded-full text-sm text-center text-white ${background} z-100 transition-all`" :style="style">
    <span><i v-if="loading" class="fa-solid fa-spinner animate-spin mr-1"></i></span><span class="whitespace-nowrap">{{ text }}</span>
  </div>
</template>

People asking from 2022 seem to also not yet get an answer.


Solution

  • As per the documentation:

    The most important implication of how Tailwind extracts class names is that it will only find classes that exist as complete unbroken strings in your source files.

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

    Don’t construct class names dynamically

    <div class="text-{{ error ? 'red' : 'green' }}-600"></div>
    

    In the example above, the strings text-red-600 and text-green-600 do not exist, so Tailwind will not generate those classes. Instead, make sure any class names you’re using exist in full:

    Always use complete class names

    <div class="{{ error ? 'text-red-600' : 'text-green-600' }}"></div>
    

    You could:

    • Have the entire class in the variable you pass to the component like

      <Component background="bg-red-400"/>
      
      <template>
        <div :class="`… {background} …`" …>
      
    • Extend the dictionary that you have:

      computed: {
        background() {
          switch (this.color) {
            case "blue-500":
              return "bg-blue-500" // this working
            case "orange-600":
              return "bg-orange-500"
            case "red-500":
              return "bg-red-500"
            case "purple-500":
              return "bg-purple-500"
            …
            default:
              console.error(`Color ${this.color} is not supported`);
              return '';
          }
        }
      
    • Use the style attribute, getting the color from Tailwind):

      import resolveConfig from 'tailwindcss/resolveConfig'
      import tailwindConfig from './tailwind.config.js'
      
      const fullConfig = resolveConfig(tailwindConfig)
      
      computed: {
        background() {
          // May need to do additional logic for nested color values, like blue.500.
          return fullConfig[this.color];
        }
      
      <template>
        <div … :style="{ ...style, backgroundColor: background }">
      
    • safelist the classes, if you have a limited number of known colors:

      module.exports = {
        safelist: [
          { pattern: /^bg-(red|green|blue)-\d+$/ },
          // …
        ],
        // …
      ];