Reputation: 6991
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.
Upvotes: 20
Views: 15173
Reputation: 4210
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! ✅
Upvotes: 0
Reputation: 594
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.
Upvotes: 1
Reputation: 89234
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.
Upvotes: 1
Reputation: 24940
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>
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:
See also : Override tailwind-css base classes
Upvotes: 5
Reputation: 148
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
Upvotes: 2
Reputation: 156
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
}
Upvotes: 0
Reputation: 1938
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.
Upvotes: 0
Reputation: 81
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>
Upvotes: 0