Catching a Tailwind: My components revelation

A huge number of people in my tech circles seemed to love Adam Wathan’s Tailwind CSS framework. But, for some reason, I just didn’t get it. Until I had this revelation about components that has caused me to go and take a serious look.

I want to understand this better!

I did a bit of a (lengthy) write up last year about my history with CSS and how I thought I should write CSS now. But the nagging sense that I was missing something with Tailwind has not gone away.

So, as I explained in my last post, I started this year with wanting to understand Tailwind and components better.

And then, suddenly, and I can’t remember where from, I had this revelation about “components”.

HOW AM I SUPPOSED TO KNOW WHAT THIS THING IS?!?!

Let’s be clear: I totally get the idea of utility CSS, and I understand the syntax to a point where I could read it but not write it. But I’ve struggled to get past the initial barriers of understanding utility-FIRST CSS, which is what Tailwind is.

I get all the arguments people make. People I admire and respect rave about the how they can build more quickly; about how Tailwind code is super easy to change and maintain. I’m not wedded to semantic class-naming or ideas about how separation of concerns should work (you’re HTML and CSS are always going to be tied together somehow).

But I looked at screenshots of Tailwind code with bafflement.

TailWind example screenshot

I fiercely held to the idea that yes, I can work out what this looks like by reading the code, but I don’t know what that thing IS. And if I want more than one of those things (the profile “card” in the image above), surely I need to extract all that code into some CSS classes that I can apply and I’m back where I started?

People talked of “extracting components” and I figured this was what they meant: pulling a load of Tailwind properties into a single CSS class so that you can re-use it.

(For those who are ahead of me…yes…I know!! Wait!!)

Great Scott!!

And then the revelation. Like an Emmet Brown Flux Capacitor moment, only without the slipping in the bathroom and bumping your head.

What if the extracted components aren’t CSS? What if, instead you extract the HTML markup to a partial?

THEN you could still have the MEANING in the project code, the “what is this?” can still be present, and you can still get the re-use.

In my head there’s a movie scene where I dash to my computer to confirm this revelation; fire up the Tailwind docs; and in some kind of strange, slow-motion dream effect, the truth becomes clear as I read the text:

Don’t rely on CSS classes to extract complex components … it’s often better to extract reusable pieces of your UI into template partials or JavaScript components instead of writing custom CSS classes.”

Tailwind Docs

A simple example

Here’s some more traditional-style markup for some buttons:

<a href="/signup" class="button">
  Sign up
</a>
<a href="/login" class="button">
  Log in
</a>

We’ll do some conversion to Tailwind. You don’t really have to know what it means for now:

<a href="/signup" class="inline-block bg-blue-300 px-4 py-3 rounded hover:bg-blue-500 hover:text-white">
  Sign up
</a>
<a href="/login" class="inline-block bg-blue-300 px-4 py-3 rounded hover:bg-blue-500 hover:text-white">
  Log in
</a>

Woah! Look at all the classes and duplication. And… HOW AM I SUPPOSED TO KNOW WHAT THIS IS?!

Now in Tailwind you could extract the classes to your own CSS component. You can use the @apply rule to bring Tailwind’s utilities into a class:

.button {
  @apply inline-block bg-blue-300 px-4 py-3 rounded;
}
.button:hover {
  @apply bg-blue-500 text-white;
}

But now we’re pretty much back where we started.

The alternative way – and the preferred way in utility-first CSS land – is to extract the HTML to a component.

You’ll need to pass in parameters for the URL and label. So you would create a template partial like this (in Laravel Blade syntax):

<a href="{{ $url }}" class="inline-block bg-blue-300 px-4 py-3 rounded hover:bg-blue-500 hover:text-white">
  {{ $label }}
</a>

And then your template with the buttons becomes:

@include('partials/components/button', ['url' => '/signup', 'label' => 'Sign up'])
@include('partials/components/button', ['url' => '/login', 'label' => 'Log in'])

With this we get all the benefits of Tailwind’s CSS: consistent spacing, fonts, and colours with ease; quick-to-write and easy-to-maintain code, and so on. But with re-usable components, and meaningful “source” template code (although the HTML output is still kinda meaningless garbage)

Get it?

Oooooh!

Exactly.

The big assumptions

I know at this point those of you experienced with components and Tailwind are wondering how on earth I didn’t understand this. But the truth is that it’s a key fact in piecing together this puzzle and not once has it been explained to me.

This understanding of components seems to be assumed. Yet to many coming from an approach like BEM CSS and WordPress world where templates tend not to be broken down into much smaller component-level partials, it’s something you have to be told or find out somehow.

All the explanations of Tailwind I’ve seen me show the code inside the component. Not the code that includes the component. And this is a critical piece of understanding how to work with Tailwind.

But what about…?

Yeah, I know, right?

If you’re still getting to grips with this, and is quite a large paradigm shift to make in your head, you probably have loads of questions about how the details of this work in practice?

  • How do I create button style variants?
  • What if I want to add some CSS to just one button?
  • Sometimes buttons are a tags and sometimes they are button tags…how do I do that?

And as I’ve gone ahead and dabbled with Tailwind, I’ve found it’s not without a lot of questions of my own.

BUT…it is quite easy to learn. It is easy to set up. It is quick to work with (if you’re working within what it gives you). It’s very comprehensive and well thought out. Adam has done a GREAT job making this thing and has my HUGE respect. And I think I can see the attraction of it.

In my next post (which may take a while to compile) I’m going to try to walk you through my explorations. I’ve recorded an hour of video that I want to cut into bite-sized chunks and then write up. Hopefully you’ll see the problems and questions I come across, and I hope you’ll come to a place where you can make your own mind up about it.

Watch this space!