Why Your Friends Can’t Shut Up About TailwindCSS — And Why They Never Will

Jorge Zreik
Vivid Labs
Published in
6 min readNov 1, 2022

Tailwind CSS. Styling messiah or organizational antichrist?

Lately, it seems that every time I open Twitter or Reddit there’s a flame war in some comments section about Tailwind. Its detractors and supporters both speak about it with a fanaticism that I haven’t seen since old Reddit posts trashing PHP (wait, that’s still happening too).

This is even more relevant in my life now that my co-founders and I decided to build Vivid, our in-browser styling editor, to support Tailwind before any other CSS solution. Vivid lets you apply and preview Tailwind styles while directly editing your source code, all from your own app’s dev server, fun stuff!

A demo of Vivid’s functionality, including editing code in-browser, applying styles via shortcuts, and resizing components with the mouse.
Some of the cool things you can do with Vivid :)

Despite the obvious issue of whether Tailwind is good or bad, this begs a much deeper question:

Why?

Why have programmers as a whole spent massive amounts of time and energy discussing this topic? And why is it that after years of this debate, there’s been virtually no agreement at scale?

At the risk of being yet another voice in the screaming horde that is the Tailwind debate, I’m here to get meta and answer that question.

Tailwind???

In a nutshell, Tailwind is a utility-first CSS framework (feel free to skip this section if you’re already a Tailwind ninja).

“CSS framework” because it lets you write CSS through it. Instead of throwing down some good old CSS like background-color: #f63344, slapping that on a class like landingPage_btn_primary, and applying it to your component, you do things the ✨Tailwind way✨.

“Utility-first” because the ✨Tailwind way✨ is all about utility classes which apply simple styles. Instead of the traditional CSS example in the paragraph above, which likely applies many more styles needed for your component, Tailwind has you apply classes like p-4 for padding or bg-red-500 for a red background. Kind of like putting legos together to mix and match the styles you need.

Essentially, you can:

  1. Write all your CSS inline
  2. In a more concise way
  3. That abides by a configurable set of standard values

Why The Bloodlust

Reading the above, Tailwind seems awesome. So why do people hate it? I can think of 3 major reasons

  1. Long class strings are ugly
  2. Inline styling breaks separation of concerns (SOC)
  3. Styles are no longer reusable

This Header Is About As Long as an Average Tailwind Class String and It Gets Very Annoying Very Quickly

This is just so easy to show rather than tell:

<div class="flex flex-1 justify-between sm:hidden">
<a href="#" class="relative inline-flex items-center rounded-md border border-gray-300 bg-white px-4 py-2 text-sm font-medium text-gray-700 hover:bg-gray-50">Previous</a>
<a href="#" class="relative ml-3 inline-flex items-center rounded-md border border-gray-300 bg-white px-4 py-2 text-sm font-medium text-gray-700 hover:bg-gray-50">Next</a>
</div>

Yes, this is a real example of Tailwind in action taken from the TailwindUI site itself. As you can see, not that I have to point it out, the sheer number of classes you have to apply to an element to fully style it is pretty huge.

Simply for the factor of code readability, this is a clear downside.

Separate Those Concerns

In the days of vanilla HTML, CSS, and JS websites, it was easy to split apart all your code by concerns. html files for markup, structure, and content, js files for functionality, and css files for styling.

This made sites like CSS Zen Garden possible where by simply swapping out a stylesheet you could change the entire look of a website without modifying its content or functionality.

All of these variations are from a simple stylesheet swap!

Since styles in Tailwind are co-located with the components that use them, we have markup, functionality, and styling in the same place, which entirely breaks separation of concerns.

The Copy-Paste Revolution

Finally, and one of the biggest criticisms of Tailwind, is the fact that Tailwind styles are NOT reusable.

Whereas with traditional CSS you can combine all the styles for a heading, including size, font color, etc, in a single class, in Tailwind you have to write them all out individually. Of course, you can make your own utility classes using the @apply rule, but that is essentially a Tailwind cardinal sin* (in most cases, see the endnote for elaboration).

This leaves people often repeating their already very verbose classes just to get some simple styling in. Given all these downsides, why is Tailwind useful at all? Well, my hypothetical reader, I am glad. you. asked.

Tailwind: A New Hope

I’ll be brief. Tailwind is good when you modularize your styling at the component level. That’s all there is to it! Article over.

Well…

To give more context, the best way to use Tailwind all comes down to addressing the downsides people rightly point out with how it’s often used. In the diagram below, you can see the difference between the traditional SOC model and the way Tailwind should be used.

A diagram of SOC on the left and Tailwind on the right. SOC shows classes being applied to components, while Tailwind shows Tailwind and HTML together that are then called as components.
Can you tell I’m an artist?

Basically, you can make your styling reusable by making your components reusable. This is what you should be doing anyway now that many people are building with tools like React where modularizing functionality is already the norm.

By modularizing your styles as components rather than classes you get rid of many of the problems people see in Tailwind:

  1. You have a huge degree of style reusability by being able to nest components. Want to reuse text styles? Make a typography component! Layout? Layout component! And all at the JS layer.
  2. SOC is essentially dead, but you no longer have to maintain a mapping between classnames and components which was mostly always 1-to-1 anyway. Additionally, styles are easy to edit by changing your Tailwind config or your fundamental UI components.
  3. Class strings… are still long, but that’s best left for another article.

In fact, this approach seems to be the trend with component libraries as a whole.

Libraries like Material UI simply give you a set of components to use that come pre-styled, with the ability to customize them as needed. Several other component libraries like Tailwind UI even get this done using Tailwind! Many people love this way of handling styling, and I love that Tailwind lets you bring the same experience to your own project.

In a sense, you can think of Tailwind as the perfect tool to build your own internal component library, however big or small you need it.

Worth the Effort?

In the end, whether or not to use Tailwind is a personal preference. The component-level modularity that I love is hands-down great in my opinion, but the same can be done using vanilla CSS or CSS-in-JS.

Tailwind does provide a benefit, however, in standardizing CSS usage across a codebase.

Having preset values for things like sizing and colors is incredibly useful, and Tailwind’s ability to customize those values as well as using @apply correctly can bring huge benefits to teams. And I’m glad to report that it’s already working wonders at Vivid — definitely check it out if you want to make the transition to Tailwind a whole lot faster and easier.

All in all, the debate will continue, but I do hope that people make it a more fair comparison by noting how Tailwind is best used and arguing their points off of that.

* @apply is usually brought up as an anti-pattern, and it often is, but it can be useful. For example, we made an @apply rule to combine text-transparent and bg-clip-text in order to get gradient text. In cases like this where you’re making what amounts to another utility class (and not something that should really be a component) it works very well!

--

--