The People versus Tailwind - the case for and against Tailwind

TailwindCSS has been around for a while now (v0.1 was released back in 2017) and remains a contentious choice for developing CSS, with many arguing for and against it's utility-based class approach. In this post, I will summarise the case for and against using Tailwind, passing down judgement on whether it should go straight to jail or be your default tool of choice.

So, what is it?

If you're not already familiar with TailwindCSS, it's a CSS framework focused around using utility-based classes. Essentially, Tailwind provides a ton of utility classes for everything from setting colours (background, font, border etc.), font size / weight, to layout helpers for css grid and flexbox.

The main tagline is:

Rapidly build modern websites without ever leaving your HTML.

How it achieves this goal is via the use of utility classes. No longer do you have to switch back and forth between HTML and CSS. Before using it, my own opinion on this would have been that this would easily get out of hand. Sure it may be fine for a basic layout, but how would this look for even a simple button component. One where you'll need to have different variants, handle state changes for hover, focus, disabled etc.

Put (Tail)wind in your sails

So why should you use it over regular good old css, semantic class names or even the old reliable - bootstrap.

To quote the creator of TailwindCSS, Adam Wathan:

"Best practices” don't actually work.

I've written a few thousand words on why traditional “semantic class names” are the reason CSS is hard to maintain, but the truth is you're never going to believe me until you actually try it. 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.

This is front and centre on the homepage, and basically in his opinion, the old fashioned way of creating semantic class names to apply your styles isn't great. He goes into a lot more detail in his post, but the gist of it is that taking a utility-first approach will help resolve many common pitfalls around consistency in the former approach.

And honestly this resonates with my own opinion before I'd actually given it a solid go, but after using it for the past few months, it feels both strange and slower to go back and write css the way I used to.

Utility-based Approach

So, if you're not already familiar with the utility-based approach, it can initially look quite messy. The examples shown below are of some baseline classes to style a button and that's not even all of them, more will be applied to change the colour, size etc. based on the variant selected.

An example of a few class names applied to a button component An example of a few class names applied to a button component

image 20231027 101851 The CSS styles that the Tailwind classes would translate into

In the second image, you can see a rough translation of how these classes would be written in normal css. The approach TailwindCSS uses may put you off, but if you look at it closely, you'll see the styles are generally grouped together in relevant sections. For example, all the focus styles are next to each other and the styles relevant to the layout for flex are next to each other, and so on. This was done automatically by using the Prettier plugin.

The Case for the Defence

Okay, now that we know the philosophical approach behind Tailwind, why would you use it? Here are the key points for the defence:

1. Clarity / Understandability

All of the styles that can be applied to an HTML element are specified in the class attribute of the element, including all of its various states e.g. focus, hover, etc. This means that an element's applicable styles can be understood simply by examining the element. This information is typically scattered across the HTML and the CSS, making traditional CSS harder to manage, especially at scale.

2. Consistency

While projects using CSS may have many different ways of doing things, Tailwind enforces a consistency in it's naming conventions and how it's styles are applied through its class names, which:

  • Enforces consistency via naming, and provides powerful ways of adding one off styles e.g. using arbitrary values.
  • Allows for certain fallbacks to be added automatically e.g. -webkit and -moz.

3. Composability:

Utility classes can be combined to create ever more intricate stylings to an element. Tailwind is like the declarative equivalent of well-written imperative or FP code. You end up with far more small functions, each doing one thing, and end up with far less code overall to manage and maintain. This becomes an increasingly important attribute as systems increase in size. Tailwind's real value is at scale.

4. Faster Development

As you can update styles without changing context, everything is done in the same file. Some may look at that as a disadvantage, but in this juror's opinion it's definitely a faster way to work, plus you can reason about an element's style more easily.

5. Compatibility

It can help with using new CSS features without worrying about compatibility, having to implement fallbacks/polyfills etc.

6. Optimised

Tailwind's CLI tool will only include the classes you use in the output css file. Since many of these classes will be reused, the end result can be very efficient.

7. Tooling

It has excellent IDE support with a range of plugins that help make it more accessible and easy to use:

  • Plugins for IDE's to provide autocomplete on classes (including custom classes for any colours or typography you've added.
  • The Prettier plugin can be used to auto-sort and group the class names so that your class attributes are easier to read and reason about.

8. Fantastic Documentation

Tailwind's documentation is exceptional and features many useful examples of the classes in use. This is great for anyone with less experience using CSS, or even those who haven't kept up to date with the ever-evolving standards.

The Case for the Prosecution

The case for the prosecution centres on 3 main witness statements:

1. Verbosity

Having lots of classes in the HTML means that the HTML can look significantly more verbose than the semantic class name approach, although this can be partially mitigated through use of the plugins above (and toggling word wrap in your IDE) and having less and simpler actual CSS.

You can use @apply to extract and reuse the styles (though this is only recommended for small and highly reused content like form controls e.g. inputs, buttons etc.).

2. Variants

Creating components with multiple variants (e.g. a button with a primary, secondary, tertiary appearance) is more effort than the semantic equivalent.

  • To help with this, there's a great library called class-variance-authority (CVA) which will allow you to create typesafe components with mutliple variants.
  • There's a great video on Vercel's YouTube channel about building out a component library for Next.JS using TailwindCSS and CVA.

3. Syntax

It can take a while to get used to the syntax and different prefixes used, although once you get used to the patterns, this will become second nature.

The Verdict

For me, this is a pretty open-and-shut case. Whether you're already familiar with CSS or completely new to it, I believe the benefits of Tailwind far outweigh any perceived downsides. Without any reasonable doubt, I would recommend giving it a go in your next project.

Article By
blog author

Joshua Barber

Senior Software Engineer