(When) is Tailwind right for you?

It appears that Tailwind is somewhat contentious: it's either the best thing since sliced bread or literally provides no value. While such extremes might make for interesting reading, the proper way to evaluate technologies is to attempt to understand the problems they solve, and then determine whether those are problems you actually have.

So let me try to help with that. In a nutshell, Tailwind is worth considering if you:

  • don't have an eye for design,
  • use a component-based architecture, and
  • prefer simple build tooling.

Let me elaborate.

Constraints set you free

Let me start with what I think is both Tailwind's main benefit and the one that's most often overlooked: its constraints.

On first sight, it looks like Tailwind provides just a bunch of CSS classes that each represent a single style declaration:

<article class="bg-blue-200 p-5">
  <h1 class="text-3xl">Corporate Ipsum</h1>
  <p class="py-2">
    Leverage agile frameworks to provide a robust synopsis for high level overviews.
    Iterative approaches to corporate strategy foster collaborative thinking to further the overall value proposition.
  </p>
</article>

Technically, an equivalent result could be achieved with inline styles:

<article style="background-color: #bfdbfe; padding: 1.25rem;">
  <h1 style="font-size: 1.875rem; line-height 2.25rem;">Corporate Ipsum</h1>
  <p class="padding-top: 0.5rem; padding-bottom: 0.5rem;">
    Leverage agile frameworks to provide a robust synopsis for high level overviews.
    Iterative approaches to corporate strategy foster collaborative thinking to further the overall value proposition.
  </p>
</article>

That's about the same amount of work!

However, take note of what you can't do with Tailwind: while you can apply vertical padding of 0.25rem (py-1) or 0.5rem (py-2), you cannot set it to 0.3rem! Likewise, while you can set the background colour to #dbeafe or to #bfdbfe, you cannot set it to #c8d2fe.

Tailwind's constraints are minimal enough that no two websites created using it look the same, but strong enough to practically enforce consistency throughout. Regardless of whether you use a p-5 here and a p-2 there, all possible values have been explicitly chosen to complement each other without anything looking "off". Likewise, Tailwind includes a default colour palette allowing you to use different shades of the same colour, both complementing each other and in most cases providing sufficient contrast to ensure everything is visible even in a sunny environment or for users with visual impairments.

A good designer will have an eye for such consistency. However, they are not always around, and even when they are, designs are rarely exhaustive. A constraint-based design system like Tailwind will assist engineers in making the right design choices when they need to do so.

Other tools that can help you achieve this goal are: Styled System, or a set of custom Sass or CSS variables (e.g. Universal Tokens).

The right abstraction

One of the reasons Tailwind felt "wrong" to me when I first saw it, was because it went counter to how I've always been taught I'm supposed to do things.

So let's consider how we were supposed to do things, why we were supposed to do them that way, and whether those reasons still apply.

The core idea behind CSS, as illustrated by the venerable CSS Zen Garden, was that you use semantic HTML to describe what the content of your page is (e.g. a heading, emphasised text, a link, etc.), and CSS to determine what it should look like (e.g. larger, in italics, underlined, etc.).

In other words, the idea is to take your DOM structure as a given, and use CSS as the source of truth for what the website should look like: for example, perhaps links inside a profile card should be bold, whereas links inside the main content should not.

Like all abstractions, this comes at a cost. The most important of which is the almost inevitable case of append-only CSS: since it's hard to tell whether a particular rule still matches anything on the site, it's practically impossible to delete unused styles.

It also turns out that separation of concerns isn't as clear-cut as might have been hoped: it is rare that achieving a desired layout does not involve adjustments to both CSS and HTML.

This is an important reason why Single-Page Application frameworks like React, Vue, Svelte and Angular encourage architectures in which applications compose together components consisting of particular combinations of different elements. These are then accompanied by CSS that style those components' particular combinations of elements in the desired way.

In other words: in practice, changing what a component looks like often involves changes to both that component's HTML and CSS. And if that's the case, is that split still worth it? Is this particular abstraction still carrying its weight?

Tailwind's answer is no. Why add component-specific classes, if those components already take care of making our styles reusable?

Tailwind puts the component in charge of styling, instead of a global stylesheet tailored to a particular combination of DOM elements. This gives you the ability to reuse styling across your app, the confidence to remove unused code, and a single place to change when updating styles.

Other tools that help defining component-specific styles are one of the various naming conventions, or one of the various CSS-in-JS tools like CSS modules, JSS, styled-components or Emotion.

Simple tooling

With the exception of the use of naming conventions, most attempts to make CSS more predictable in a component-based architecture involve relatively complex tooling. This often requires multiple layers of your stack to be aware of this tooling, makes dependency upgrades more painful, can introduce delays to your development flow, and in the worst case impacts the performance for your users.

With Tailwind just relying on CSS classes, it is relatively simple and independent of the rest of your tooling: all you really need is a CSS file that includes the definitions of the Tailwind classes you use.

Granted, Tailwind defines so many classes that you can't feasibly just dump all of them into a stylesheet and call it a day: the resulting stylesheet would take far too long to download. Instead, it needs to generate a stylesheet defining just the classes you use. The good news is: generating such a stylesheet can be done using relatively "dumb" tooling: Tailwind just considers all its class names, and checks which of those literally occur in your code base. No need for something as complex and brittle like parsing your HTML, JSX, or whatever language you're writing in.

Sure, the flip side is that if you also happen to have a Markdown file that happens to mention md:bg-blue-100, that class will also be included even though it's not actually used anywhere. But if that happens to a few classes, the impact is negligible, and certainly worth the tooling simplicity.

So when is Tailwind right for you?

If you can use some help to make your designs look consistent, use a component-oriented architecture, and would like to avoid complex tooling, I can warmly recommend you to give Tailwind a try sometime.

And if not... Tailwind might just not solve a problem you have, and that's fine too!

(This article was adapted from a Twitter thread.)

License

This work by Vincent Tunru is licensed under a Creative Commons Attribution 4.0 International License.