Doing the same thing all the time is boring !
This often happens when you have to apply the same style to child elements with the same function, if you want to change something, you have to do it individually for each element.
Fortunately today's css allows us to write selectors that can make it easier for us to manage the style of child elements through their parent, and in this article we are going to find out how to do it with tailwindcss.
To show you the relevance of applying tailwindcss utilities to child elements via the parent, I will guide you in building a simple card by focusing on user avatars where you will apply a custom variant.
Common use
What we often do is to add tailwindcss utilities to each child element :
<img class="h-14 w-14 rounded-full ring-4 ring-white object-cover duration-300 hover:ring-blue-100" src="" alt="" />
This is a natural way of applying css classes to an element but you probably know that adding a lot of classes can make your html difficult to read and repetitions are boring to see. We are used to this because of tailwindcss and can't complain about it when you know the advantages it provides.
My avatars stacked list will look like
<div class="flex -space-x-2">
<img class="h-14 w-14 rounded-full ring-4 ring-white object-cover duration-300 hover:ring-blue-100" src="" alt="" />
<img class="h-14 w-14 rounded-full ring-4 ring-white object-cover duration-300 hover:ring-blue-100" src="" alt="" />
<img class="h-14 w-14 rounded-full ring-4 ring-white object-cover duration-300 hover:ring-blue-100" src="" alt="" />
<img class="h-14 w-14 rounded-full ring-4 ring-white object-cover duration-300 hover:ring-blue-100" src="" alt="" />
<img class="h-14 w-14 rounded-full ring-4 ring-white object-cover duration-300 hover:ring-blue-100" src="" alt="" />
</div>
There is still ways to limit repetitions in your html when using tailwindcss : Creating a component css class with the @apply directive to group all the utilities, or using JavaScript Frameworks like Angular, React, Vue, Svelte… to build custom components.
I prefer adding all utilities to an element and I sometimes don't use a Frontend framework so the efficient way to limit repetitions when building the avatars stacked list of my card will be to apply all classes to the <img src="" />
tag via the parent element.
In css we'd basically use this selector :
.avatars>*{
width :3.5rem;
height : 3.5rem;
}
Arbitrary variant
One of the best features of tailwindcss is the ability to add values or selectors that are not by default in the framework directly in your html so you don't need to write css no more.
Applying this with tailwindcss will look like :
<div class="[&>*]:w-14 [&>*]:h-14"> </div>
And the whole list should be :
<div class="flex -space-x-2 [&>*]:h-14 [&>*]:w-14 [&>*]:rounded-full [&>*]:ring-4 [&>*]:ring-white [&>*]:object-cover [&>*]:duration-300 hover:[&>*]:ring-blue-100">
<img src="" alt="" />
<img src="" alt="" />
<img src="" alt="" />
<img src="" alt="" />
<img src="" alt="" />
</div>
Like me you would certainly get tired of seeing the [&>*]
arbitrary variant and a readable name will make easier to use and reuse.
Create a custom variant
To fix this, create a custom variant with a readable name that you will use instead of [&>*]
.
You need to do this in your tailwind.config.js
To get started import Tailwind’s plugin function from tailwindcss/plugin
.
const plugin = require('tailwindcss/plugin');
const plugin = require('tailwindcss/plugin');
module.exports = {
theme: {
extend: {
// ...
},
},
plugins: []
}
After importing the plugin function you can now create the custom variant inside the plugins array. Call the addVariant function, passing in the name "children", and a format string &>*
that represents how the selector should be modified.
const plugin = require('tailwindcss/plugin');
module.exports = {
theme: {
extend: {
// ...
},
},
plugins: [
plugin(function({ addVariant }) {
addVariant('children', '&>*')
})
]
}
Now you can replace the [&>*]
arbitrary by the custom variant you have just created in the config file.
The html should now look like :
<div class="flex -space-x-2 children:h-14 children:w-14 children:rounded-full children:ring-4 children:ring-white children:object-cover children:duration-300 hover:children:ring-blue-100">
<img src="" alt="" />
<img src="" alt="" />
<img src="" alt="" />
<img src="" alt="" />
<img src="" alt="" />
</div>
Conclusion
This way of doing can make your html less difficult to read because it prevents from repeating again and again the same utilities to the child elements that have the same function and designed the same.
Top comments (3)
What if I want to change one particular child from parent?
You can use :where() pseudo class for that
eg : [&>*:where(ul)]
so many 'fixes' to problems that dont even exist when you just write regular css or use any other utility like sass lol.