Back to Articles
CSS
Tailwind
Web Development
Architecture

The CSS Tailwind War (and Why Both Sides Are Right)

June 15, 20266 min read

I was never a fan of Tailwind until I understood why it was created. The debate is not about which is better. It is about which problem you are solving.


I was never a fan of Tailwind.

For years, the sight of a fifty-class string on a single div made me wince. It looked like inline styles wearing a disguise. It violated every separation-of-concerns instinct I had.

Then I used it on a real team with real deadlines.

And I understood why it exists.

This post is not about crowning a winner. The CSS versus Tailwind debate is exhausting because both sides are arguing from different assumptions. The real question is not which is better. It is which problem you are solving.

Why People Hate Tailwind

The critics are not wrong.

Tailwind produces HTML that looks like this:

<div class="flex items-center justify-between px-4 py-2 bg-blue-500 hover:bg-blue-600 text-white rounded-lg shadow-md">

That is a lot of presentational noise in your markup. The cognitive load is real. You must mentally decode px-4 into padding-inline: 1rem, mt-1 into margin-top: 0.25rem. It is a language on top of a language.

And the separation of concerns argument is legitimate. HTML should describe what something is, not how it looks. When your markup becomes tightly coupled to a specific visual style, you lose the ability to restyle without touching every template. The CSS Zen Garden dream dies.

There is also the learning curve. Learning Tailwind means learning abbreviations, breakpoint prefixes, arbitrary value syntax, and modifier chains. That is a significant investment in framework-specific knowledge that does not transfer. Teams using Tailwind often lose proficiency in actual CSS: specificity, cascade, inheritance, container queries, @scope, and @layer.

Modern CSS has evolved into something powerful. Native nesting, container queries, cascade layers, and custom properties solve many of the problems Tailwind was created to address. When you flatten everything into utility classes, you give up that power.

Why People Love Tailwind

The fans are not wrong either.

The biggest thing Tailwind gives you is speed. You do not switch files. You do not name classes. You do not decide whether a component is .media-card or .content-card or .info-box. You write flex items-center gap-4 rounded-xl bg-white p-6 shadow-lg and move on.

The consistency is the real killer feature. Adam Wathan analyzed major CSS codebases and found staggering inconsistency:

  • GitLab: 402 unique text colors, 239 background colors, 59 font sizes
  • GitHub: 163 text colors, 147 background colors, 56 font sizes
  • Stripe: 189 text colors, 90 background colors, 35 font sizes

That is what happens when you give developers a blank canvas. Tailwind removes the blank canvas by constraining choices to a predefined, harmonious design system. You get consistency for free because deviating is harder than complying.

Bundle size is another win. Tailwind generates only what you use. Your CSS stops growing linearly with every new feature because you are reusing the same utilities. With the JIT engine, you see the exact same CSS in development and production.

And maintenance at scale is simpler. Changing a design system value happens in one config file, not across hundreds of component stylesheets. Adding or removing a class only affects the element it is applied to. You never worry about accidentally breaking another page that uses the same CSS.

The Real Divide: Colocation vs. Separation

The debate is not about syntax. It is about two different beliefs:

Colocation: Structure and style should live together because they change together. When you modify a button, you should edit one file, not two.

Separation: Structure and style should be independent because they serve different purposes. HTML is content. CSS is presentation. Coupling them creates fragility.

Both are valid. Both have tradeoffs. The question is which tradeoff matters more for your context.

When to Choose Pure CSS

Choose CSS when:

  • You are building a content-heavy site where markup needs to outlive the current design
  • You have a small, experienced team that values platform knowledge and long-term maintainability
  • You are leveraging modern CSS features heavily: container queries, @scope, cascade layers, native nesting
  • You are building a design system that must be framework-agnostic
  • You want to minimize build complexity and framework lock-in

In these cases, CSS Modules, scoped styles, or modern CSS with custom properties give you the control you need without the abstraction tax.

When to Choose Tailwind

Choose Tailwind when:

  • You are prototyping or building an MVP where velocity matters more than architectural purity
  • You work on a team where multiple developers touch UI and consistency is hard to enforce
  • You are building a component-based application (React, Vue, Svelte) where duplication is solved by extracting components, not CSS classes
  • You need a design system that developers actually use, not just a Figma file or a CSS variables document
  • You want to eliminate the blank canvas problem and reduce bikeshedding over naming and values

In these cases, Tailwind is a design system compiler disguised as a CSS framework. It encodes best practices and eliminates repetitive decision-making.

The Convergence Nobody Talks About

Here is the part that makes the debate feel outdated.

Tailwind is becoming more CSS-native. Version 4 uses CSS custom properties for all design tokens, @layer for organization, and color-mix() for color manipulation. It is embracing the platform it once abstracted away.

Meanwhile, modern CSS is becoming more component-friendly. Native nesting, @scope, and cascade layers make it easier to write maintainable, scoped styles without preprocessors or utility classes.

The gap is shrinking. Both sides are moving toward the same goal: predictable, maintainable, scalable styling.

The Mental Model

You cannot appreciate React if you have never written pure HTML and CSS, manipulated the DOM, and used the browser APIs directly.

The same is true here.

You cannot appreciate Tailwind if you have never maintained a sprawling CSS codebase where every new feature adds new CSS and every refactor is a archaeology expedition. You cannot appreciate modern CSS if you have never felt the pain of a fifty-class string that no one dares to touch.

Both are CSS. Both solve real problems. Both create real problems when used in the wrong context.

Final Point

The CSS Tailwind war is not about syntax. It is about two different philosophies of how to organize software.

If you value long-term maintainability, platform alignment, and the full power of the browser, pure CSS is the better choice.

If you value team velocity, enforced consistency, and rapid iteration, Tailwind is the better choice.

Most teams do not need to pick one forever. They need to pick the right one for the project they are building today.

The tool is not the problem. The problem is using the wrong tool and then blaming it for the mismatch.

At the end of the day, it is all CSS.

Enjoyed this article?

Quick reaction helps me write better follow-up posts.

Connect with me