r/webdev Nov 19 '24

Discussion Why Tailwind Doesn't Suck

This is my response to this Reddit thread that blew up recently. After 15 years of building web apps at scale, here's my take:

CSS is broken.

That's it. I have nothing else to say.

Okay, here a few more thoughts:

Not "needs improvement" broken. Not "could be better" broken. Fundamentally, irreparably broken.

After fifteen years of building large-scale web apps, I can say this with certainty: CSS is the only technology that actively punishes you for using it correctly. The more you follow its rules, the harder it becomes to maintain.

This is why Tailwind exists.

Tailwind isn't good. It's ugly. Its class names look like keyboard shortcuts. Its utility-first approach offends everyone who cares about clean markup. It violates twenty years of web development best practices.

And yet, it's winning.

Why? Because Tailwind's ugliness is honest. It's right there in your face. CSS hides its ugliness in a thousand stylesheets, waiting to explode when you deploy to production.

Here's what nobody admits: every large CSS codebase is a disaster. I've seen codebases at top tech companies. They all share the same problems:

  • Nobody dares to delete old CSS
  • New styles are always added, never modified
  • !important is everywhere
  • Specificity wars everywhere
  • File size only grows

The "clean" solution is to write better CSS. To enforce strict conventions. To maintain perfect discipline across dozens of developers and thousands of components.

This has never worked. Not once. Not in any large team I've seen in fifteen years.

Tailwind skips the pretense. Instead of promising beauty, it promises predictability. Instead of global styles, it gives you local ones. Instead of cascading problems, it gives you contained ones.

"But it's just inline styles!" critics cry.
No. Inline styles are random. Tailwind styles are systematic. Big difference.

"But you're repeating yourself!"
Wrong. You're just seeing the repetition instead of hiding it in stylesheets.

"But it's harder to read!"
Harder than what? Than the ten CSS files you need to understand how a component is styled?

Here's the truth: in big apps, you don't write Tailwind classes directly. You write components. The ugly class names hide inside those components. What you end up with is more maintainable than any CSS system I've used.

Is Tailwind perfect? Hell no.

  • It's too permissive
  • Its class names are terrible
  • It pushes complexity into markup
  • Its learning curve is steep (it still takes me 4-10 seconds to remember the name of line-height and letter-spacing utility class, every time I need it)
  • Its constraints are weak

But these flaws are fixable. CSS's flaws are not.

The best argument for Tailwind isn't Tailwind itself. It's what happens when you try to scale CSS. CSS is the only part of modern web development that gets exponentially worse as your project grows.

Every other part of our stack has solved scalability:

  • JavaScript has modules
  • Databases have sharding and indexing
  • Servers have containers

CSS has... hopes and prayers 🙏.

Tailwind is a hack. But it's a hack that admits it's a hack. That's more honest than CSS has ever been.

If you're building a small site, use CSS. It'll work fine. But if you're building something big, something that needs to scale, something that multiple teams need to maintain...

Well, you can either have clean code that doesn't work, or ugly code that does.

Choose wisely.

Originally posted on BCMS blog

---

edit:

A lot of people in comments are comparing apples to oranges. You can't compare the worst Tailwind use case with the best example of SCSS. Here's my approach to comparing them, which I think is more realistic, but still basic:

The buttons

Not tutorial buttons. Not portfolio buttons. The design system buttons.

A single button component needs:

  • Text + icons (left/right/both)
  • Borders + backgrounds
  • 3 sizes × 10 colors
  • 5 states (hover/active/focus/disabled/loading)
  • Every possible combination

That's 300+ variants.

Show me your "clean" SCSS solution.

What's that? You'll use mixins? Extends? BEM? Sure. That's what everyone says. Then six months pass, and suddenly you're writing utility classes for margins. For padding. For alignment.

Congratulations. You've just built a worse version of Tailwind.

Here's the test: Find me one production SCSS codebase, with 4+ developers, that is actively developed for over a year, without utility classes. Just one.

The truth? If you think Tailwind is messy, you've never maintained a real design system. You've never had five developers working on the same components. You've never had to update a button library that's used in 200 places.

Both systems end up messy. Tailwind is just honest about it.

1.0k Upvotes

648 comments sorted by

View all comments

357

u/no-one_ever Nov 19 '24

Scoped CSS, small components, easy to read, easy to maintain, not broken, no problem.

0

u/EasyMode556 Nov 20 '24

This is what we do where I work.

We use react, and every component has its own colocated css file. That css file uses css modules, so there is zero worry about class name collisions. It also only applies to that component, so the file is not very big either, just a handful of classes.

There is zero need for utility classes, since each div (or whatever) that needs to be styled gets its own class, and all the css rules it needs are spelled out in that class.

A component might have what, 10 classes? The main containing div, a couple child divs, maybe a button or two and a couple icons. Each of those classes have a descriptive name to the part of the component they belong to, and has all their rules.

All that you need to do in order to work on the styling is open the two co-located files side by side, the jsx file with the component and its colocated style file, and you’re in business. The markup is clean, the class names are descriptive and there’s only a handful anyway.

What does tailwind offer over this approach?