Reputation: 6004
I want to create some custom styles for my UI and in the official Tailwind documentation described 2 options to accomplish it.
So far I understand that @apply just creates a custom style class and adds it to the Tailwind system. It's exactly what I need and it's fine but I'm also wondering about the @layer directive.
Based on the description it adds a bucket of custom styles to the tailwind layout system but I can't understand what benefits this move give to us.
What if I just use @apply and that's all?
Will it harm performance?
So I'm just trying to understand in what cases should I use @layer
Thanks for any help | info!
P.S. Sorry if my question is stupid. I apologize if it is so. I'm new in Tailwind.
Upvotes: 14
Views: 16938
Reputation: 14333
Actually you can freely use both (or none of them) at the same time - there are no restrictions. You can even not to use @tailwind
directives but you will loose whole point of using Tailwind then. And no - @apply
directive does not adds custom styles into Tailwind's system (it just converts utility class into CSS property and works kinda as CSS alias) while @layer
does add styles into Tailwind.
There are few benefits described by Tailwind itself
- Tailwind will automatically move any CSS within a @layer directive to the same place as the corresponding @tailwind rule, so you don’t have to worry about authoring your CSS in a specific order to avoid specificity issues.
Tailwind "separates" all classes into three categories - base
(any base styles, e.g. heading, paragraphs, images - it is modified normalize.css), utilities
(one-property classes - e.g. text-sm
responds only for text size) and components
(multiple CSS properties, like buttons, containers, etc). However the border between these definitions is quite blurry
Let say we have this CSS file
@tailwind base;
@tailwind utilities;
Here you may inject these styles by using @tailwind
directives - @tailwind base
will inject all Tailwind's base styles, any styles registered via @layer base
and registered via config file or plugins.
And if you define base style for h1
tag one after another
@layer utilities {
h1 {
@apply text-7xl;
}
}
@layer base {
h1 {
@apply text-2xl;
}
}
Despite text-2xl
was called later and you would expect it will overwrite text-7xl
in fact you will see the opposite - that is because utilities
were injected after base
in compiled file. Change the order
@tailwind utilities;
@tailwind base;
and now h1
will be styled by text-2xl
utility. It may help to keep track of high-priority CSS selectors placed in different source files
- Any custom CSS added to a layer will only be included in the final build if that CSS is actually used in your HTML, just like all of the classes built in to Tailwind by default.
Let's register two buttons
@tailwind base;
@tailwind components;
@tailwind utilities;
.btn-blue {
@apply px-4 py-2 inline-block bg-blue-500;
}
@layer components {
.btn-red {
@apply px-4 py-2 inline-block bg-red-500;
}
}
And HTML file would be (we're using only one of them)
<button type="button" class="btn-blue">
Button
</button>
If you compile CSS you will see only .btn-blue
class being compiled in final CSS. That means that any non-used components registered via @tailwind components
or config will be purged from final build. However if you change HTML into
<button type="button" class="btn-red">
Button
</button>
You will see both .btn-blue
and .btn-red
in compiled file. So in this case .btn-blue
acts like regular CSS - it has not being purged despite it is not used. So answering on "Will it harm performance" - in some manner yes, as using @layer
directive prevent unused styles to be compiled into bundle. It is good for reusable components "from project to project", where let say you have input, button, select components, etc, but not every project will use them
- Wrapping any custom CSS in a @layer directive also makes it possible to use modifiers with those rules, like hover: and focus: or responsive modifiers like md: and lg:
This simply means that you can use components classes with variants like hover:btn-red
- all px-4 py-2 inline-block bg-red-500
now will be applied only on hover.
In order to make sense let's change HTML a little
<button type="button" class="hidden sm:btn-red">
Button
</button>
Now you can see on mobile devices button will be hidden and only after sm-breakpoint button styles will be applied. You CANNOT do the same with sm:btn-blue
- as it is not registered as component and Tailwind does know nothing about it
Same is valid for native Tailwind components or any
<div class="sm:container">
I will behave as container only after 640px screen width
</div>
Another way to use it - override defined properties. Back to red button you will see it has px-4
property. But of you wish ypu may change it
<button type="button" class="btn-red px-8">
Button (with px-8 being applied)
</button>
<button type="button" class="btn-blue px-8">
Button (px-8 being ignored)
</button>
There are almost no restrictions in using variant with @apply
so instead of hidden sm:btn-red
you can use simply btn-red
and change CSS into
@layer components {
.btn-red {
@apply px-4 py-2 hidden sm:inline-block bg-red-500;
}
}
P.S. In all examples I've used @apply
directive - however you may write any CSS instead or even mix them
Next part is opinion based and can be skipped
Despite it's a good feature to have I personally almost never use it. I never had issue with selector orders or stacking custom components with variants. Maybe hidden sm:btn-blue
may have more potential to readability - like you know for sure it is hidden on mobile and only after some breakpoint there will be button in this place
It is good unused styles may be purged. However there may be some situations where you do NOT want such behaviour - when your classes comes from external API or backend and you still want them to be compiled in final build. This way either safelist it or just don't use @layer
at all
Also if I starts a new project with predefined UI-kit, I'm always sure, I will use .btn-blue
class - and if not - why should I even create such stylings in a first place?
So it's up to you and your project would you like to use it or not
Upvotes: 29