21

I have created a VueJS button component using TailwindCSS. My goal is to provide that button component with some base styles (using tailwindcss classes), with the option to override them when need be (again, using tailwind css classes).

For example, here is a simplified version of the Button component:

// Button.vue

<template>
  <button class="bg-green-500 text-white py-2 px-4 rounded">
    Click Me
  </button>
</template>

And here is an example of my using that component in another file:

// index.vue

<Button></Button>
<Button class="bg-red-600"></Button>
<Button class="bg-blue-600"></Button>

The problem is that this only half-works. That is to say, bg-blue-600 does override the bg-green-500 that I set up as a default in Button.vue. But bg-red-600 does not override the background color (presumbably, because bg-red-600 comes earlier in the css source code.

As such, I am wondering how can I properly set this up? That is to say, how can I give the Button component some base styles (again, using tailwind css classes) while also providing the option to override those styles using tailwind css classes.

Thanks.

8 Answers 8

5

Use ! important operator infront of any class to override existing class.

The important option lets you control whether or not Tailwind’s utilities should be marked with !important. This can be really useful when using Tailwind with existing CSS that has high specificity selectors.


Explanation:

Tailwind in case of conflicts uses the latest className while styling (Not necessarily true all the time)

Example:

<div class="bg-black h-screen bg-green-600"></div>

Output: enter image description here

The bg-black is overridden by bg-green-600.


How to get bg-black ?

Use ! operator infront of bg-black as !bg-black

<div class="!bg-black h-screen bg-green-600"></div>

Output:

enter image description here

See also : Override tailwind-css base classes

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

Comments

3

To use the initial:* variant, with defined zero specificity. Details are here:

Override Tailwind classes of a reusable Vue component without using props: https://dev.to/saifobeidat/override-tailwind-classes-of-a-reusable-vue-component-without-using-props-660

2 Comments

I tried the initial: variant but the code doesn't seem to work, tried different things but no result. If you have a working example would be great, seems to be a clean solution
The tailwind-unimportant plugin mentioned in this answer uses exactly this idea, but also handles that fact that giving the new styles zero specificity leads to the base tailwind styles overwriting them.
1

Arbitrary variants can be used to increase the specificity of the generated selector to allow later classes to always be applied.

In this case, use [&&]:bg-blue-600 for the class name to overwrite the style for bg-green-500. To overwrite it again later, you can use another class with an increased number of ampersands (&), e.g. [&&&]:bg-blue-700.

For special cases, the !important modifier can be applied to override nearly anything else. This can be done by adding ! in front of the class name, e.g. !bg-blue-600. Use this sparingly, as it can make styles difficult to maintain and modify later on.

For an explanation of why this occurs, see the Multiple Same CSS Classes issue.

Comments

1

The tailwind-unimportant plugin for Tailwind solves this problem. It adds a variant that reduces the specificity of the component classes so that they can be overridden.

// Button.vue

<template>
  <button class="-:bg-green-500 -:text-white -:py-2 -:px-4 -:rounded">
    Click Me
  </button>
</template>
// index.vue

<Button></Button>
<Button class="bg-red-600"></Button>
<Button class="bg-blue-600"></Button>

There's also the tailwind-merge, a JS library that will de-duplicate these clashing classes.

Comments

0

As a workaround, you can use props:

<!-- Button.vue -->
<template>
  <button :class="background + ' text-white py-2 px-4 rounded'">
    Click Me
  </button>
</template>

<script>
export default {
  props: {
    background: {
      type: String,
      default: "bg-green-500",
    },
  },
};
</script>
<!-- index.vue -->
<Button background="bg-red-600"></Button>
<Button background="bg-blue-600"></Button>

Comments

0

This is because your component attributes class on Button does not tickle down to the html button. To do this just bind the attributes to the child like so

<button v-bind="$attrs"...>

This will make all the attributes you specify on the Button (which are not props) bind to the html button.

That being said, I personally prefer making a button class using the @apply directive and reusing it across my project.

1 Comment

In vue2, which this question is tagged with, class does indeed trickle down, so I think your answer is misleading
0

If you create a tailwind class using the @apply directive, you can add in !important to make it override the other color classes when used.

You will need to use the lang="postcss" attibute to use tailwind directives in a component.

<style lang="postcss">
.my-overriding-class{
    @apply bg-red-600 !important 
}

2 Comments

In Tailwind 3 you can prefix any class with ! to add !important— e.g. !bg-red-600
@Ryan post that as another answer
0

Tailwind-merge seems like the best answer

from my research and experience so far.

NOTE: I didn't build it in anyway, just discovered it through the Tailwind discord server.

Step 1: Install yarn add tailwind-merge

Step 2:

<template>
  <button class="text-white py-2 px-4 rounded" :class="twMerge('bg-green-500', $attrs.class)">
    Click Me
  </button>
</template>

<script setup>
import { twMerge } from 'tailwind-merge'
</script>

Whatever you want to be able to override put in the twMerge first argument string.

Then use how you'd expect, and you're done! ✅

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.