Tailwind CSS is a toolset CSS framework that has been described in detail in many articles on the web. This article is not a retelling of the official document, nor is it a list of the series of advantages, author Gerard will start from another perspective, under the premise of trying to keep objective, based on the actual development of the scene, points out some problems existing in Tailwind CSS. In fact, there are a number of drawbacks to Tailwind CSS beyond those mentioned in this article, such as insufficient support for a high degree of customization and the mental burden of remembering a large number of predefined class names.

As a warning, you may not agree with this article, because our opinions are always influenced by our own knowledge and experience. But more importantly, it may be the author’s attitude towards emerging technologies, which, in his own words, is: “When everyone is Shouting that it’s awesome, it’s usually a good moment to sit down and have a good look at it”

The text begins.

  • Tailwind CSS Is (Probably) Overhyped
  • Gerard Van der Put
  • Translator: Chor

The introduction

Over the past two years, Tailwind CSS has grown in popularity (from 30K downloads per week to 600K today). There’s no doubt that this popular utility-first CSS framework has many advantages. Chances are you’ve heard how amazing and powerful it is, because that’s what a lot of developers think.

But we have a lot more to say about this framework.

What is Tailwind CSS?

If you’ve never seen Tailwind in action, check this out:

<div class="bg-gray-100 rounded-xl p-8">Hello World</div>
Copy the code

The class name here reflects the definition of Tailwind: a collection of predefined classes (called utility classes). You don’t need to write basic CSS style rules, just apply predefined class names directly to HTML.

There are many more such class names. The following list shows some of the categories and their examples:

  • background (bg-gray-200.bg-gradient-to-bl)
  • Elastic layout (flex-1.flex-row)
  • Grid layout (grid-cols-1.col-span-4)
  • padding (p-0.p-1)
  • size (w-1.h-1)

This collection of predefined classes has previously been likened to “Lego bricks” that can be used in code. Of course, it has a lot of overlap with traditional CSS, but it doesn’t stop there: it also includes predefined ranges (BG-RED-100, BG-RED-200, etc.), for example. Tailwind was designed to make our development more efficient, and in a way it did.

At the same time, I like the name: Tailwind. I take the boat out when I’m free, and the wind is a good thing.


As shown above, we write the utility class name directly in HTML. It will quickly come to mind that this is very similar to inline CSS, which may explain why the Tailwind developers mentioned it at the beginning of the documentation.

While they try to explain it as one of its flaws (and I don’t deny that it has many virtues), I’m still not sure about the grammar. I don’t want to contaminate every element of my HTML structure with a bunch of class names, nor do I want to be confronted with code that looks like this every day:

Note: The above code comes from Tailwind’s documentation and all it does is render a simple card. In fact, it turns out to be very nice, even responsive. But if you look at our daily development, the situation deteriorates rapidly: What if I’m developing a component that’s more complex than a card? What if I had to follow a designer’s design style and put up with his “little quirks”?

I tried to deal with this, and the result was predictable — every HTML element was littered with Tailwind utility class names. Official documentation and instructional videos won’t tell you this, but it’s a real question for us when we start building big apps:

// A bunch of class names<div class="sm:w-4 md:w-6 lg:w-10 xl:w-full sm:text-sm md:text-base lg:text-base xl:text-2xl flex-1 sm:flex-none bg-black sm:bg-white rounded-md sm:rounded-none">Hello World</div>
Copy the code

This is inevitable in real development.

The above example is not an exaggeration, I would even say it is the most simplified example — at least for apps that have specific requirements and specific design styles (responsive variations and style adjustments based on different screen sizes).

So how do you organize these class names? Maybe we need to create and follow a sort, but that’s too complicated. The alternative is to allow the template designer and developer to use either specific sort, but in this case, in order to find the target class name to modify. We have to scan the code horizontally or even scroll through it.

I don’t want to look for the font size of an element the way I look for Willy.

My point is that some HTML elements use a lot of styles, and in such cases you should consider separating styles from HTML tags and putting them in a separate file. This way, we can organize the style and make it more readable. You can’t cram all CSS functionality into the class HTML tag property, and neither can Tailwind. Doing so only makes the HTML structure more bloated.


Tailwind allows us to use their class names in a single CSS file for the problems mentioned above:

.header {
  @apply bg-red-200 w-4 text-gray-400 rounded-sm border-red-400 border-2;
Copy the code

But I don’t see any advantage over the traditional way of writing CSS (or other preprocessors like SASS). Call me a fuddy-duddy, but I do prefer to write this way:

.header {
  background-color: #FECACA;
  width: 200px;
  color: # 444;
  border-radius: 5px;
  border: 2px solid #F87171;
Copy the code

Again, in real development, elements can apply a lot of styles.

I haven’t shied away from the benefits of Tailwind, and some of the toolclasses it offers are definitely more useful to explore. But when it comes to syntax, I want a clear separation between markup language (HTML) and style rules. This is a subjective opinion, I think.

Clean up useless code

After Tailwind is introduced into the project, all class names are available. But we obviously don’t need to use all class names when building and packaging projects. Therefore, Tailwind uses the tool PurgeCSS:

This is where PurgeCSS comes in. PurgeCSS analyzes your content and CSS files. First it matches the selectors used in the CSS file with the selectors in the content file. Then it removes unused selectors from the CSS to produce smaller CSS files.

To summarize: First, we introduced a large number of utility class names to the project, and then, when we were ready to build and release the project, we used a tool to scan the code and find all unused class names to make sure they weren’t packaged with the rest of the code. Implementation depends on the following regular expression:

Introducing and using Tailwind would add another layer of complexity to our project, and with that complexity comes the risk of causing problems for our development. Such as:

  myItems.map(item= > (
    <div className={`item level-The ${item.level} `} >
    </div>)); ;Copy the code

Dynamically generating class names like this is not possible. This meant that Tailwind was limiting our development. This is also mentioned in the documentation, but it’s easy to miss:

String concatenation is not allowed.

Development constraints are one thing, but adding another layer of complexity to a project often poses a risk.

It ultimately becomes a matter of judgment: does Tailwind do more good than harm? The answer to this question varies from project to project, but we should at least be aware of the problem. The problems mentioned above are just the tip of the iceberg when it comes to Tailwind’s limitations. As another example, adding additional (custom) CSS to a Tailwind project is not straightforward.


After reading Tailwind’s documentation and working on it for a few days, I couldn’t help but think that the authors didn’t realize that most of us already use other tools to simplify style writing in our daily development.

One of the benefits of using Tailwind, according to the documentation, is that you can avoid magic numbers. Indeed, this is one of its advantages: we define a color utility class such as BG-Red-200, which can then be used throughout the code and change its actual value in one place (Tailwind’s configuration file). It smells good, and I’m sure you’ll agree.

But today’s tools, such as SASS (downloaded more than five million times a week), have long made it easy to create utility classes and variables and reuse them in code. Even native CSS already supports the use of variables.

When we use SASS or native CSS, we don’t have to face an extra layer of complexity, nor do we need to change established conventions and syntax when writing CSS style rules.

There is a cost to using Tailwind. Spend time and effort learning Tailwind’s syntax and class names, and you’ll gradually forget the syntax behind it: the syntax of native CSS. If my developers use Tailwind for a year on a larger project, they will gradually forget about native CSS. Is this state of affairs really optimistic? I’m not sure.

After the order

Tailwind is popular, and its appeal and following is growing. I can understand why, after all, we can really benefit from using it. I also agree with its merits, and some of its utility classes can be very useful.

My purpose in writing this article is to show you the fact that there are always two sides to a story.

Some people will benefit from this framework, but others will be limited, and they will discover these limitations as they go along — or worse, after development.

Be critical as you adapt to the new framework. When “everyone” is screaming their wonderment, it may be a good time to sit down and take a closer look.

Thank you for your time!