This blog is now Tailwind-free
When I redesigned this blog 2 years ago, I decided to give the Tailwind CSS framework a spin. Fast-forward to today: Tailwind is now entirely gone, replaced by some simple, well-structured Sass code. This was not an easy transition โ it took me over 8 hours of dedicated effort, with no way to automate the task at hand. I think that in and of itself might be an argument against Tailwind, but that probably sounds like circular reasoning if you don't understand the why, so allow me to elaborate.
Why Tailwind in the first place?
The author of Tailwind wrote a lengthy explanation for why Tailwind exists in the form of an exploratory blog post. His argument stems from the dependencies created by writing HTML & CSS the "traditional" way, where you define class names in HTML and then use those names as entrypoints for CSS styles. It's a well-articulated thought experiment, and it was good enough to convince me at the time.
As for the actual experience of using Tailwind: it's generally fine. The tooling meshes well with my static site generator (Eleventy). It enabled me to whip up a decent-looking blog with not much effort. And, indeed, it mostly eliminates the cross-language dependency between HTML classes and CSS specifiers.
But there were also some immediate annoyances, along with some slow-burning pain points that would gradually make tweaking the site's design more and more frustrating.
Why no Tailwind now?
I'll try to sum it up in a couple of reasons.
Tailwind destroys the relationships between similarly-designed components. In the aforementioned blog post, those relationships are framed as a thorn in the developer's side, forcing a choice between coupling, duplicating, or extending code โ with no clear winner among the three. After fully utili-fying the example CSS into Tailwind classes, the author ceases to use "separation of concerns" or "dependency direction" as rhetorical tools, which might cause the reader to miss the tradeoff that was made: Tailwind chooses duplication of code and then obfuscates it by spreading it across the HTML.
This is how my blog ended up with the exact Tailwind incantation
flex flex-wrap gap-x-4 items-baseline
repeated seven times across 5 different files.
One of them had text-sm text-shadows-500 tacked onto the end,
and another one existed in a container with twice as much vertical spacing as the rest.
Going into the conversion process,
I had no idea that two of them were notably different, let alone why they were different!
Maybe this isn't a problem for everyone, but it's a problem for me. I like to have a decent mental model of how my site is styled, so that when I go to add something new, I know where to find existing styles to copy or reuse. Under Tailwind, I would likely end up copying one of them at random for the 8th instance, essentially rolling the dice on which "version" of the component gets to propagate.
Tailwind's naming conventions are all over the place. Quick, tell me what each of these Tailwind classes expands to:
- items-baseline
- justify-center
- content-start
- align-middle
If you know CSS but not Tailwind, you can probably spot the problem here immediately. All of these correlate to 3-word incantations in CSS (a 2-word property followed by a single-word value), but each one drops a word, and it is nearly impossible to intuit the mapping:
- align-items: baseline;
- justify-content: center;
- align-content: start;
- vertical-align: middle;
Sometimes
Tailwind pulls a new word out of a hat,
casting away CSS's naming conventions for the sake of terseness.
letter-spacing? No, we call that tracking around here.
line-height? Nah, look it up, it's leading now.
Sometimes it changes things just enough to throw you off,
like dropping the hyphen from CSS's white-space property
in favor of whitespace.
Sometimes Tailwind just doesn't have a standardized keyword value for a property. That was going to be its own subsection, but I'm struggling to find where this happened to me and it's too general of a problem to search for online.
Circling back to the intro:
Tailwind is easy to add, but obnoxious to remove.
In case you weren't aware of how it works,
you give it a file pattern (say, "./src/**/*.liquid", "./src/**/*.html")
and it scans all the matching files as plain text
for any substrings that look like Tailwind classes.
Once it's tallied up all the matches,
it writes a CSS file containing exactly the utility classes it thinks it saw.
Any false positives will slightly increase the size of the output file,
but otherwise have no effect.
The fact that Tailwind doesn't care what language(s) you're using
is kind of genius for adoption.
While competing platforms like Sass have to maintain bindings for various languages,
Tailwind brings the equivalent of grep to the table
and instantly covers all those languages and more.
Unfortunately, this property of Tailwind
is also (part of) why it's so hard to remove from a project.
All the functionality encapsulated in the Tailwind class lists
gets mixed into a soup of alphabetized utility classes,
completely lacking any semblance of semantic relationship by design.
Tailwind doesn't know about the abstract syntax tree of your HTML;
there is no parser to throw in to reverse.
All you can do is comb through your site,
name your nameless classes,
and carefully substitute every instance of my-2 with margin: 0.5rem 0;
and so on.
Finally, I like the CSS platform and I want to use it. This is why I committed to ditching Tailwind, despite the significant time investment. Its value proposition isn't strong enough to make me want to write Tailwind class strings when I could write CSS classes instead.
The Sass-ified version of the website
has slightly different metrics on nearly every page.
There were more than a few cases where I realized
my Tailwind design led to unnecessary stacking of margins / padding.
My line heights were also all over the place
because Tailwind likes to specify it in rem
and then change it in tandem with the font size,
rather than setting a ratio like 1.75.
Ultimately, the conversion process was a good opportunity to use my eyes
and undo whatever weird decisions Tailwind pigeonholed me into.
Despite the extremely monotonous & mechanical process,
I think the site came out looking slightly better.