DEV Community

Paweł Ludwiczak
Paweł Ludwiczak

Posted on • Updated on

TailwindCSS @apply - the right approach?

I've been experimenting with Tailwind quite a lot recently and there's one thing that I can't figure out... Which of these is better:

.element {
  @apply bg-red ... hover:bg-green ... focus:bg-yellow ...;
}
Enter fullscreen mode Exit fullscreen mode

or...

.element {
  @apply bg-red ...;

  &:hover {
     @apply bg-green ...;
  }

  &:focus {
    @apply bg-yellow ...;
  }
}
Enter fullscreen mode Exit fullscreen mode

The latter example is probably more readable but on the other hand it doesn't utilize Tailwind's variants. So I'm wondering if there's any difference between one and the other? Maybe performance?

Top comments (12)

Collapse
 
tedgoas profile image
Ted Goas

I don't know that there's a huge difference for most sites. If you're using tailwind classes in markup, you have to include everything on one line and use the hover:* and focus:* classes.

But if you're using Tailwind classes in CSS files, I think either way makes sense. You could even combine selectors using your latter example:

.element {
  &:hover,
  &:focus,
  &:active {
    @apply bg-green;
  }
}
Enter fullscreen mode Exit fullscreen mode

Instead of writing three classes for hover:bg-green, focus:bg-green, and active:bg-green.

Collapse
 
pp profile image
Paweł Ludwiczak

Maybe I wasn’t clear enough: I’m looking specifically at bringing Tailwind classes into my components’ CSS files. And my question is whether I should be using Tailwind’s variants (.el { @apply hover:bg-green; }) OR stick with CSS native pseudo classes (.el:hover { @apply bg-green; })?

Collapse
 
tedgoas profile image
Ted Goas

Nope you were clear, I'm saying that I don't think it matters which way you do it. The CSS that Tailwind outputs for its variants is pretty much the same as when you would be outputting by using regular classes inside a :hover {} selector.

Tailwind is nice in that it gives you 2 or 3 ways to do things.

Thread Thread
 
pp profile image
Paweł Ludwiczak

Oh sorry then, maybe I misunderstood your comment initially :)

Anyway - I'm just curious which of these "2 or 3 ways" is more efficient and performant (and IF there is any difference).

Collapse
 
lyrod profile image
Lyrod

Hum, am I missing something? CSS does not support nested selector, so you need to do
.class:focus, .class:hover... { @apply... }

Right?

Collapse
 
pp profile image
Paweł Ludwiczak

Oh, I forgot to mention I use SCSS as preprocessor - but that shouldn’t change anything👍

Collapse
 
ninofiliu profile image
Nino Filiu

@aleksandrhovhannisyan makes a very good point about @apply in his article that has been trending in hacker news:

If it’s not already obvious, @apply completely violates Tailwind’s founding and guiding principles. The fact that this jailbreak even exists is troubling. What exactly is the difference between using @apply and just using the CSS rules that correspond to your utility classes? There is no difference—except now, you’ve defeated the point of using a utility CSS framework in the first place, and you’re better off just writing vanilla CSS to begin with.

Collapse
 
pp profile image
Paweł Ludwiczak • Edited

I'm not sure if I agree with this one. I have a codebase that doesn't use any dynamically generated components (like React - where one file can be responsible for one component). It's more static codebase - with files for entire views and/or parts of it. There's definitely not a react-like component for Buttons - you have to create them by hand.

So it makes perfect sense for me to use utility classes to set up layouts, grids, etc but I'd had to repaste 20 exactly the same utility classes for every of my button

<button class="bg-red text-white px-4 py-2 ...">...</button>
Enter fullscreen mode Exit fullscreen mode

Instead it makes sense to create old-school cool button.css file with something like

.btn {
  @apply bg-red text-white px-4 py-2 ...;
}
Enter fullscreen mode Exit fullscreen mode

And while using utility classes elsewhere in the views (for defining some generic layouts and grid), I still need to create more old-school CSS-only components. You can say that I could do something like this:

.btn {
  background: var(--red);
  color: var(--white);
  padding: var(--s2) var(--s4);
  ...
}
Enter fullscreen mode Exit fullscreen mode

...so I don't have to use @apply but then the question is how to keep my CSS vars in sync with Tailwind (which I'm not sure supports vars that well - I could be wrong here though).

That being said, I think it makes perfect sense to use utility classes in HTML in some places with combination of @apply approach for creating pseudo-components.

Collapse
 
malloryerik profile image
mallory-erik

Really late answer, but Tailwind in general lets me develop with speed. I can experiment and create designs uniquely fitting my domain. @apply allows me to clean up and standardize the mess I've made as needed, like a halfway point before converting everything to pure CSS. Maybe you can think of Tailwind as development speed and flexibility on credit, so there's a minor technical debt you accrue. You can "refinance" that debt with @apply. Finally some day, if need be, you can pay it off entirely by switching the whole thing to "proper" CSS.

Collapse
 
smndhm profile image
Simon • Edited

Hello, I was facing the same this week, I ended to organise my tailwindCSS like this :

.element {
  @apply bg-red ...;
  // Hover
  @apply hover:bg-green ...;
  // Focus
  @apply focus:bg-yellow ...;
  // Active
  @apply active:bg-blue ...;
}
Enter fullscreen mode Exit fullscreen mode
Collapse
 
pp profile image
Paweł Ludwiczak

I do like this approach!

Collapse
 
hayksaryan profile image
hayk-saryan

Yo may as well just use CSS