The Stigma Surrounding TailwindCSS

Share on Twitter

Being an active Twitter user, where most people come together to shout at each other, I see Tweets hating on TailwindCSS pretty much weekly at this point. All of these Tweets hating on TailwindCSS have these six things in common.

And this cycle pretty much continues forever. There is pretty much no point in arguing with the Tailwind haters. Most Tweets like this are just to grab attention, and it works.


The specific Tweet that made me write this blog post, was this (The one I quoted). The rage baity-ness of these Tweets are so common that when I see them appearing on my timeline, I already know what’s coming next.

So, what happened to that specific Tweet?

As I had expected, Theo noticed the Tweet, the OP got the attention they wanted, and everyone moved one.

Now I don’t blame the OP, nor Theo. Through Theo’s POV, it can be frustating to see misinformation about an useful technology go viral every other week which may make many people question the technology they are using. Also, from the OP’s perspective, I can see why they might post such a rage-baity Tweet. It’s the easiest way to get attention (Even if its negative). You don’t change a winning formula.

But why Tailwind in particular?

Now, there are many reasons for the hate being particularly for Tailwind. Most of the anti-Tailwind crowd has the following points to say about Tailwind:

Sure, there are some more, but these are the main four points are discussed about. Now I, as a TailwindCSS user, would obviously be a little biased. I have defended the technology a lot, but still, I believe that these points are nothing more than just “Trying to search for one more reason to hate a technology”, also that technology most of the time is something that they don’t even use. But the question still remains, “Why Tailwind specifically?”. These are just the “cons” of Tailwind. Well, I think the reason is mainly because of the framework-y nature of Tailwind. As in, Tailwind being a set of utility classes, that works with the component model of frameworks like React and Svelte. With components, you can apply styles to each one directly without name collisions. This however is not that big of a problem in regular HTML, where you usually just have one CSS file, and zero separation of the UI. Therefore, this hate for frameworks directly translates into the hate for Tailwind. Since most of these people, are something I like to call “The Web Dev Purists”. A group of people, who hate anything with frameworks. Love web components. Too much JS = Bad. Pure & Accessible HTML = Good. JSX bad, React bad, and this is where comes the “Tailwind bad”.

”Separation of concerns”

This point is brought up very often when it comes to Tailwind. Tailwind has no separation of concerns because you directly put the style in the markup. This is actually a plus point of using it, and whenever someone brings this “No separation of concerns” point up, I always view it as “I never actually cared about separation of concerns, but its a good point against Tailwind so I’m going to use it against the technology” Separation of concerns is… well it depends if its good or awful depending on the problem that is being solved. In Web Development, especially in CSS, separation of concerns often leads to unnecessary code that are often unused styles, which get added into the CSS bundle, especially in a component-based framework. TailwindCSS’s utility approach instead is atomic. You use the classes you want, you don’t include the classes you don’t. So you can compose a small portion of classes together for the UI of one component or page rather than repeating the same style with a slightly different look on each element that needs to be styled.

What about Web Components instead of frameworks?

Web Components are fine, but they are terrible to work with. So much so, that Google themselves created two frameworks to fix them. Yeah, two frameworks (tbf one’s deprecated now) to solve the problem of a flawed API of a concept that was supposed to solve the framework problem. When it comes to Tailwind, vanilla JS (or TS) + Web Components don’t really work great with it. Since in JS, creating stuff manually is verbose, and especially appending stuff to the elements created is even more lengthy to write. Even for a simple component example like the one below, appending Tailwind classes aren’t that intuitive. Not to mention they probably won’t work with Tailwind intellisense.

// Also, imo, class based APIs suck for UI components
class Paragraph extends HTMLElement {
  constructor() {
    super();
    /* ...Initialize shadow root and stuff... */
  }

  connectedCallback() {
    const p = document.createElement("p");

    // C'mon, is this really that much better than just writing scoped CSS in a WC?
    p.className = "text-xl text-green-500";

    /* ...Attach to shadow root... */
  }
}

window.customElements.define("html-paragraph", Paragraph);

Compare this to frameworks where most of this looks like regular HTML markup.

<script lang="ts">
  // Svelte example
</script>

<p class="text-xl text-green-500">Never gonna give you up</p>

Also, the main reason people hate Tailwind is because it requires a build step. Web components are meant to be a solution to create components in JS without the need for a framework, which consequently means no buildstep.

The “Right click > Inspect” way of proving Tailwind’s ugliness

Here’s the markup that you would see on my site’s home page if you open Inspect.

Markup of siri.dev's home page

Looks messy on the surface right? But the code I wrote for it looks way different.

<html lang="en">
  <head>
    <!-- ... -->
    <ViewTransitions />
    <title>{title}</title>
  </head>
  <body class="h-screen w-screen overflow-x-hidden subpixel-antialiased text-white bg-dark-gray">
    <Navbar />
    <input type="checkbox" id="menu-hidden" class="hidden" />
    <SideMenu />
    <main class="overflow-hidden pt-36 p-8 min-[1181px]:p-32 ${className}">
      <BackgroundEffect />
      <slot />
    </main>
    <footer />
  </body>
</html>

Clearly, it isn’t the mess you see in the dev tools, its separated into individual components. Like the snippet here is the <BaseLayout /> (Layout for all pages except the blog posts) The index.astro (Home page) file uses this layout, and builds with it to create the page.

This is why I believe that a straight up dev tool inspect isn’t the most definitive way to prove something about a website, because with modern-day build tooling, there maybe like 10-steps setup before the website is deployed. You can’t just pull up an inspect and tell me this is what you have to write to style stuff with Tailwind.

The hate for build tooling

The majority of the hate for build tooling comes from the past, when Webpack was a complete YOLO to any developer switching from a backend server framework to a frontend JS-heavy framework. The problem with Webpack is the config. Since it was, and still is to an extent the most popular bundler, it has a large eco-system of plugins. And when you go down the rabbit hole, you realize that not only do you need to configure Webpack (Which in itself is a challenge because there are just way too many “tweaks” you can make), but you also need to configure each plugin. This means endless documentation searching before getting to the point of starting to build you client application.

In the current times though, this is no longer a problem. At all. Tools like Vite completely eliminate the config problem, and rarely do you need to touch the config anymore. Every framework is trying to use a unified, minimal-config tool for bundling. Like Vite which is being adoped by major frameworks, or Turbopack, which is the next gen successor to Webpack (Written in Rust btw) that will have minimal or no config.

But still, putting aside the “Web Dev Purist mentality”, people had the bad experiences with these tools before, and refuse to look back at them with a new mindset now, when they are much better. This has resulted in the hate for build tooling. And consequently, the hate for Tailwind because it needs a build step. The Web dev purists hate build tools in general, but Tailwind, relying on it heavily (since it generates the CSS file at build time) becomes a major target for criticism for these people. Of course there have been many attempts trying to use Tailwind in a mostly non-build environment, like the BETH stack which uses the Tailwind CLI to generate the CSS file as you write your code. But still, a build step never hurt no one. Maybe you will have to wait some time before your new deployment is live, but otherwise I don’t see any reason not to have a build step when necessary.

Does this mean Tailwind is perfect?

Of course not. No technology is perfect. The reason many other styling solutions like StyleX are still emerging is because Tailwind doesn’t work great for everyone. Dealing with styles for a large company like Meta may lead to another solution, but if it works for them better than Tailwind, then let them use whatever. Tailwind isn’t for everyone. Some people may not like the verbose nature and may like type-safe styles instead. And I’ve seen that happen a lot with technologies like PandaCSS. In that case, there’s no reason to stick to a technology you don’t like.

Ending it

TailwindCSS itself is a great technology. But the influx of haters recently on Twitter has put a negative view of it in many people who haven’t themselves tried out. Tailwind itself is one of those “You can never leave” technologies. You use it once, your hate suddenly disappears, and it becomes your go-to styling solution. But of course, social media clout is desired. Some people will do anything to get engagement, and of course, share rage bait for a technology they never used is a part of it.