I love Tailwind CSS

| frontend tools css

I’ve been disconnected from frontend work for a while - my work on data at Measure Studio seldom requires me to poke in there. However, in working on several side projects I had to brush up on my FE chops a bit. A friend pointed me towards Tailwind. I struggled to understand it at first, but once it clicked - it was glorious. I love Tailwind CSS.

Rough beginnings

I started mucking about with CSS a long time ago. Back then, every freelancer kind of built their own bag of tricks - something like a very limited framework or toolkit. It helped us do projects quicker, and while they may look different from one another, the “bones” were all the same with some custom sprinkles on top.

That’s why when I discovered Boostrap, I was fully on board - this was what I was doing anyway, so might as well. I learned it by heart and never looked back. Almost every project started by figuring out how to import the latest version of Bootstrap, then copying and pasting the requisite markup to make everything click together. And that worked well enough.

Customization is the enemy of delivery

Until, of course, it didn’t. As every CRUD developer knows, forms are the bane of all existence. Almost every CRUD I worked on needed something more spicy in its forms at some point, and almost universally at that point it turned out that Bootstrap got in the way.

It was all downhill from there, of course. Weird tricks, nasty hacks, the ever-dreaded !important or fifteen. It was a bloody mess. In time, every project grew two style trees - the one where was applied everywhere, and the one for the forms. Or should I say - at least two. If the project was not managed strictly enough, it just grew sprinkles of inline style, or controller-specific stylesheets.

And developers grew gray hair trying to figure out whence a given brand of b*llshit was coming from to ruin their day. A customer deciding to re-brand and/or change their color scheme was a cause of grave stares, heavy groans, and googling the earliest happy hour nearby.

Catching wind

I recently decided to redesign this very website. I just have to every few years, once it no longer speaks to me. This site is extremely simple, only a few files for layout, so it seemed like a manageable project.

I fired up the docs, tried to make a CodePen with Tailwind, and… ruh roh. No go. Turns out current-version Tailwind has an entire CLI, a preprocessor, a this, a that…

I almost scrapped the entire project altogether. Thankfully, I found the excellent Tailwind Play environment to help me get started. It has nice, focused autocomplete, which meant I grepped the docs less and built more.

I completed the entire redesign in about four hours. And it only took this long because I got obsessed with the dot-journal pattern in the background on the top of this page (sorry, mobile users, you can’t see it). I could’ve been done in about an hour.

Once Tailwind clicks, it really clicks. It makes internal sense: if you know how one bit works, you can usually guess correctly how another bit works. With some exceptions - such as I expected the flex-basis to be controlled by the flex-basis class, but it’s controlled by basis instead. Nothing a quick trip to the docs won’t help with.

Take only what you need from here

Another nice thing about Tailwind is that, while it has features for almost everything under the sun, the CLI is smart enough to only bundle the classes you actually use. Since this blog only uses a few, it’s bundle size is minuscule. It could still be diminished further by using @apply less.

@apply is, by the way, how you get an old curmudgeon like myself on board. I didn’t really subscribe to all this “plop the classes on every element” idea at first, but Tailwind met me where I live. I could still make a .hero class for the banner you see above, and then put in Tailwind’s styles:

.hero {
    @apply text-center;
    @apply flex items-center justify-evenly;
    @apply md:shadow-xl md:shadow-slate-700;
    @apply mb-5 md:mb-9;
    @apply rounded;
    @apply min-h-[200px] md:min-h-[400px];
    @apply p-10;
    @apply flex-col;
    @apply bg-cover bg-center;

This is equivalent to building HTML like this:

<div class="text-center flex items-center justify-evenly md:shadow-xl md:shadow-slate-700 mb-5 md:mb-9 rounded min-h-[200px] md:min-h-[400px] p-10 flex-col bg-cover bg-center">

Which, admittedly, is a bit of a mouthful. But being a mouthful, it promotes another important concept:

DRY your app, stupid

Even this simplistic app could be broken up into partials. The hero image/title box could be a partial no problem. In a Rails/Sinatra/whatever Ruby app - same thing, partials. In an SPA - good, reusable components. Then you only make this mouthful once.

And once it’s made and cleanly separated, you can update all buttons in the app with a quick code change. It’s immediately visible why this button is colored like that. If the customer wants to update their theme, it can be done with a Tailwind config change.

Many happy returns

I really enjoy the power and the developer experience Tailwind brings. The tech wins are not lost on me, either. I intend to keep it as a permanent part of my toolkit, and include it in a few side projects I’m toiling on. I wholeheartedly recommend you check it out for yourself.

And if it feels foreign, remember those wise words from Adam Wathan, creator of Tailwind CSS:

If you can suppress the urge to retch long enough to give it a chance, I really think you’ll wonder how you ever worked with CSS any other way.

The urge is there, but the road is well worth it in the end.

Hero image by Lars Nissen from Pixabay

Built with ❤ by Paweł J. Wal in 2023. Hugo helped.

Blog contents, except where otherwise noted, are CC BY-SA 4.0. Code of this blog is MIT.

Toggle dark/light mode