Tidying Your Tailwind Classes

Tidying Your Tailwind Classes

@apply composite classes in Tailwind

Love 'em or hate 'em, CSS utility frameworks are here to stay. Me, I think Tailwind CSS is awesome. Which is lucky because it's been used on everything I've worked on for the last three years. It now sounds strange if someone says they aren't using it in their project. But...

Tailwind Can Give you To Many Dam Class Names

I've still never gotten over just how messy it is in my HTML file. Call me OCD but once I get more than 15 classes on an element I just want to find some way to split them all up. Here is a sample from their homepage

Screenshot 2022-09-02 at 21.16.06.png

That black button in the image has this as the class name

  <button class="h-10 px-6 font-semibold rounded-md bg-black text-white">Buy now</button>

That used to be a nice semantic bit of code like

  <button class="button-primary">Buy now</button>

and everyone knew what that element was. Well, let's pretend we're using CSS still and put this back. But with the added advantage we'll have unified paddings, heights and border-radius from other elements on our app

The @apply directive

Tailwind gave us a really nice simple way of doing this. All we need to do is put this in our CSS file

.button-primary {
  @apply 
    h-10 
    px-6 
    font-semibold 
    rounded-md 
    bg-black 
    text-white
}

But now we've lost all the power of Tailwind. what if I want to quickly change this one button to change the colour or make the padding a little larger? This doesn't work!

  <button class="button-primary px-12">Buy now</button>

that px is just ignored because the px-12 class is less specific. We need to add it to the correct layer

Let me override my class?

In this case, we want to add it to the component layer. Then our new button class will be on the same level as all our other classes. We add it to the component layer like this:

@layer components {
  .button-primary {
    @apply 
      h-10 
      px-6 
      font-semibold 
      rounded-md 
      bg-black 
      text-white
  }
}

Now we can adjust our padding on just this one button like this

  <button class="button-primary px-12">Buy now</button>

Much cleaner. If all our buttons are going to be this style we can just make it the base button style.

Edit the button style

We can make the button style by adding it straight to the base layer like this

@layer base {
  button {
    @apply 
      h-10 
      px-6 
      font-semibold 
      rounded-md 
      bg-black 
      text-white
  }
}

now every button element in our site will have this style just by being a button. But before we go any further should we do this? Well not too much

Why to only use composite classes sparingly

Tailwind gives us four reasons to not use these composite classes too often. If you've been using CSS for a while you'll know all of these really really well:

  1. You can't really change the button-primary class without worrying about ruining everything on your site.
  2. You have to keep changing files. You didn't separate your concerns when you put the classes in a separate file. You separated your languages.
  3. You have to come up with class names and pretty soon they just become stupid
  4. It'll just make your CSS file larger because you'll be duplicating classes.

It's okay to use @apply sparingly but let's not do this every time. If we're using a js framework like React we should just create a <primaryButton /> component to create a semantic name and clean our code up.