DEV Community

Cover image for Tailwind CSS Won the War... But We're the Losers
Elvis Sautet
Elvis Sautet

Posted on

Tailwind CSS Won the War... But We're the Losers

This week, I needed to add a simple hover effect to a button. Nothing fancy. Just change the background color on hover.

I stared at the screen for 30 seconds. My fingers hovering over the keyboard. And I couldn't remember how to write it.

Not because I'm bad at CSS. I've been building websites since 2017. I know CSS. Or I used to.

The syntax just wouldn't come to me. My brain immediately went to hover:bg-blue-600. That's Tailwind. Not CSS.

Then it hit me. I haven't written actual CSS in maybe two years. Everything is Tailwind now. Classes. Utilities. No stylesheets.

And I'm not the only one. Tailwind has over 20 million weekly NPM downloads. That's more than Bootstrap's 4.9 million. The framework is everywhere. Your favourite sites/coding-Agents use.

But here's the question nobody's asking: what happens when we all forget how CSS actually works?

The Takeover Nobody Saw Coming

Five years ago, Tailwind was this weird utility-first framework some people were trying. Most developers looked at code like this:

<button class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded">
  Click me
</button>
Enter fullscreen mode Exit fullscreen mode

And said "that's disgusting. That's just inline styles with extra steps."

They weren't entirely wrong.

But something happened. Developers started using it. Then they couldn't stop using it. Then they forgot how to build without it.

The data tells the story. According to the State of CSS survey, Tailwind's retention rate is in the high 70s. That means 3 out of 4 developers who try it keep using it.

Compare that to Bootstrap at around 45%. Or plain CSS at... well, people don't "retain" CSS because it's not a choice. It's the foundation.

Except now it kind of is a choice. And developers are choosing Tailwind.

Why Everyone Uses It (Including Me)

I'm not going to sit here and pretend Tailwind is bad. I use it. On every project. My muscle memory is Tailwind classes now, not CSS properties.

Here's why it won:

Speed

You don't context switch between HTML and CSS files. Everything is right there. You see a div, you style it, you move on. No jumping between files. No naming classes. No wondering if .button-primary is already defined somewhere.

Consistency

Your spacing is consistent because you're using predefined spacing utilities. p-4 is always the same padding. gap-8 is always the same gap. No more margin: 23px because you eyeballed it.

No naming things

Naming CSS classes is one of the hardest problems in programming. With Tailwind, you don't name anything. The classes describe themselves. flex items-center justify-between tells you exactly what it does.

Just works

You don't fight specificity. You don't debug why your styles aren't applying. You don't wonder if that class is being overridden somewhere. Tailwind classes just work.

That's powerful. That's why developers love it. That's why I love it.

The Problem Nobody Talks About

But here's what's bothering me. And I think it should bother you too.

We're abstracting away fundamental knowledge

CSS isn't that hard. Flexbox, Grid, positioning, these are core web platform features. They're not going away. But we're building an entire generation of developers who don't know them.

I've interviewed junior developers who can tell me exactly what justify-content: space-between does in Tailwind class form but can't write the actual CSS property.

They know flex items-center but don't know align-items: center.

They know w-64 but have no idea that's width: 16rem or why rem exists.

That's concerning.

The bundle size lie

Tailwind markets itself as producing tiny CSS bundles. "Most projects ship less than 10kb of CSS!"

That's true. Your CSS file is small.

But your HTML is massive. Every element has 5-15 classes. Your HTML files are 2-3x larger than they would be with semantic CSS.

Sure, HTML compresses well. But it still needs to be parsed. The browser still needs to process all those classes.

I ran the numbers on one of our projects. CSS went from 45kb to 8kb with Tailwind. Great! But HTML went from 120kb to 340kb. Net increase: 183kb.

That's not mentioned in the marketing.

You're locked in

Want to switch from Tailwind to something else? Good luck. Your entire codebase is Tailwind classes. Every component. Every page. Thousands of utility classes everywhere.

Migrating away from Tailwind is like migrating away from jQuery was. Possible, but so painful that most people just don't.

You're not learning CSS. You're learning Tailwind. And if Tailwind goes away or falls out of favor, what do you have?

The readability problem

Look at this real code from a production app:

<div class="flex flex-col sm:flex-row items-start sm:items-center justify-between p-4 sm:p-6 bg-white dark:bg-gray-800 rounded-lg shadow-md hover:shadow-lg transition-shadow duration-200 border border-gray-200 dark:border-gray-700 space-y-4 sm:space-y-0 sm:space-x-4">
Enter fullscreen mode Exit fullscreen mode

That's 19 classes on one div. Can you tell what it does at a glance? Nope. You have to mentally parse each utility.

With semantic CSS:

<div class="card">
Enter fullscreen mode Exit fullscreen mode

And in your CSS:

.card {
  /* All the styles */
}
Enter fullscreen mode Exit fullscreen mode

Which is more readable? Which is easier to understand for someone new to the codebase?

What Happens If Tailwind Disappears?

This keeps me up at night. Not because I think Tailwind will disappear tomorrow. It won't. It's too big now.

But frameworks come and go. Remember when Bootstrap owned the web? When jQuery was on every site? When Flash was how you made interactive content?

All of those seemed permanent. None of them were.

Tailwind is backed by Tailwind Labs. It's a company. Companies can be acquired, shut down, pivot, or just decide a framework isn't profitable anymore.

What happens to the millions of Tailwind projects then?

You might say "it's open source, the community will maintain it." Sure. But when was the last time you saw a popular framework maintain momentum after losing its core team?

Look at Ember. Look at Backbone. Look at Angular.js (not Angular, Angular.js). All still technically maintained. All basically dead.

I'm not predicting Tailwind will die. I'm saying it could. And if it does, we have an entire industry of developers who can't write CSS anymore.

The Real Controversy (That Nobody Wants to Say)

Here's the spicy take that'll make people angry:

Tailwind is training wheels that never come off.

And that's by design.

When you learn to ride a bike, you start with training wheels. Eventually, you take them off and ride for real.

With Tailwind, you start with utility classes. And you... keep using utility classes. Forever. You never take off the training wheels and write actual CSS.

The framework doesn't encourage you to learn the underlying platform. It encourages you to learn more Tailwind.

Want to do something custom? Extend your Tailwind config(I haven't read much in the newer versions, DO NOT ROAST ME ON THAT, hahaha). Need a new color? Add it to your Tailwind theme. Need a new spacing value? Add it to your Tailwind spacing scale.

Everything pushes you deeper into Tailwind, not deeper into CSS.

And that's brilliant business strategy. Lock-in is valuable. But it's bad for the web platform.

CSS is evolving fast. Container queries, has() selector, subgrid, cascade layers, all these powerful features are landing in browsers.

But how many Tailwind developers know about them? How many are using them?

Tailwind supports some of these through utilities. But you're learning the utility, not the feature. And if Tailwind doesn't support something yet, you probably won't use it.

What I'm Doing About It (And What You Should Too)

I still use Tailwind. Every day. I'm not here to tell you to stop using it.

But I am making some changes:

One day a week, no Tailwind

Friday is my "vanilla CSS" day. If I'm working on something, I write actual CSS. No utilities. Just regular stylesheets.

It's painful at first. But it keeps my CSS skills sharp. And honestly, sometimes it's refreshing.

Teaching juniors CSS first

When I mentor junior developers, we don't start with Tailwind. We start with CSS. Flexbox, Grid, positioning, the fundamentals.

Only after they can build a layout in pure CSS do we introduce Tailwind. So they understand what they're abstracting.

Actually reading CSS specs

I subscribe to CSS updates. I read about new features. I try them in projects. Because CSS is still evolving, and I don't want Tailwind to be my only window into it.

Writing semantic CSS for complex components

For truly complex components, I write actual CSS. Custom properties, calculations, complex selectors. Things that are hard or impossible in utility classes.

This keeps me comfortable in both worlds.

The Uncomfortable Truth

We're in a weird place with CSS right now.

The platform is more powerful than ever. Container queries are game-changing. Cascade layers solve specificity problems. Nesting is finally here natively.

But fewer developers than ever actually write CSS.

Tailwind is winning. The data proves it. The adoption proves it. The community proves it.

And maybe that's fine. Maybe abstraction is progress. We abstracted away assembly language. We abstracted away C. We abstracted away jQuery's cross-browser pain.

Maybe abstracting away CSS is the next logical step.

But I can't shake the feeling that we're losing something important. The ability to understand and manipulate the foundational layer of the web.

When everyone knows Tailwind but nobody knows CSS, who maintains the web platform?

Who contributes to CSS specs? Who files browser bugs? Who pushes CSS forward?

If the answer is "nobody because we're all using Tailwind," that's a problem.

Where CSS Is Actually Heading

While we're all writing flex items-center justify-between, CSS itself is evolving into something more powerful.

Native nesting is here. You can write Sass-style nested selectors in pure CSS now.

Container queries let components be responsive based on their container size, not viewport size. This is huge and Tailwind sort of supports it but most developers don't use it.

The has() selector is a parent selector. You can style a parent based on its children. This was impossible for decades. Now it's real.

View transitions API makes page transitions smooth and native. No JavaScript framework needed.

Cascade layers give you fine-grained control over specificity. You can finally organize your CSS without fighting specificity wars.

All of this is native CSS. Browser-level features. No build step. No framework. Just works.

But how many developers are using these? How many even know about them?

Tailwind adds utilities for some of this. But slowly. And only when it makes sense for their utility-first model.

Meanwhile, native CSS is moving faster than any framework can keep up with.

The Question We Should Be Asking

Not "should I use Tailwind?" That ship has sailed. Most of us are using it or will use it.

The question is: "how do I use Tailwind without forgetting the platform?"

Because that's the real risk. Not that Tailwind is bad. But that it's so good that we stop learning what's underneath.

And when the next big thing comes (and it will come), we'll be unprepared.

We'll be Tailwind developers, not web developers.

And that difference matters.

My Honest Take (After 3 Years of Tailwind)

I don't hate Tailwind. I use it every day. It makes me faster. My team is more productive with it.

But I'm worried about the industry. About junior developers who think CSS is just Tailwind classes. About codebases that are so dependent on one framework that migration is impossible.

About a future where "front-end developer" means "knows Tailwind" instead of "knows the web platform."

Maybe I'm wrong. Maybe this is just progress and I'm being nostalgic about writing CSS files like an old man yelling at clouds.

But I don't think so.

I think we're trading short-term productivity for long-term knowledge. And that trade-off only makes sense if Tailwind stays dominant forever.

Which is a big assumption.

What You Can Do

If you're using Tailwind (and you probably are), here's my advice:

Don't stop learning CSS. Spend time with the actual properties. Understand what you're abstracting. Read CSS specs. Try new features.

Teach CSS to juniors before Tailwind. Make sure they understand the foundation before adding the abstraction layer.

Write some vanilla CSS occasionally. Keep your skills sharp. You might need them.

Stay aware of native CSS evolution. The platform is moving fast. Don't let Tailwind be your only window into it.

Build escape hatches. Don't make your entire codebase 100% Tailwind. Have some custom CSS. Make migration possible, even if unlikely.

Question the framework. Just because Tailwind says something is "best practice" doesn't mean it is. Think critically about what you're building.

The Bottom Line

Tailwind won. The data proves it. The adoption proves it. If you're arguing against Tailwind in 2025, you've already lost.

But winning doesn't mean it's perfect. And popularity doesn't mean it's the final answer.

CSS is the platform. Tailwind is a tool. Don't confuse the two.

Use the tool. But respect the platform. Learn the platform. Contribute to the platform.

Because when the next framework comes (and it will come), the platform will still be there.

And you'll need to know it.


What's your take? Are you forgetting CSS too? Or am I overthinking this?

Drop your thoughts. Let's argue in the comments like developers do.

Elvis Sautet

Follow me on x at @elvisautet

Senior Full Stack Developer | Still Writes CSS Sometimes

If this made you uncomfortable, good. Share it anyway. We need this conversation.

Top comments (31)

Collapse
 
xwero profile image
david duymelinck

The main problem for me is that to mimic CSS people are creating frameworks on top of Tailwind, like shadcn/ui. We know creating abstraction layer on abstraction layer is a recipe for failure.

While the idea of utility classes is great, Tailwind took it to the extreme. When you take one thing to the extreme, and follow that mindset you are missing out options that make code simpler.
There are not many languages that are only OOP or functional, most of them combine programing paradigms.

I think the elephant in the room is why are the designs not preventing you from needing to resort to utility classes. Designs should give consistency. Utility classes are for exceptions.

Collapse
 
maxart2501 profile image
Massimo Artizzu

ShadCN is another utterly loathsome idea: it's basically a dependency without being an actual dependency. Meaning it's not versioned. It doesn't have tests. You're not familiar with its code. And yet, you're tasked with its maintainance, becase it's in your codebase.

And you downloaded from a source that's outside the usual security radars (i.e. ShadCN's repo).

Collapse
 
designzbyoj profile image
DesignzByOJ

That's a great point about abstraction layers, then when one domino falls, all the rest do too, then we'll be more reliant on AI to pick up the missing pieces (since so many are going for vibe coding, including myself).

Collapse
 
brandon_pliska_0c288a6a5d profile image
Brandon Pliska

Not vibe, agentic.

Collapse
 
adithyasrivatsa profile image
Adithya Srivatsa

Man… this hit way too close. Tailwind’s great and all, but it really did turn half of us into “hover:bg-whatever” machines.
Kinda wild how fast you forget actual CSS once you stop touching it.
I open a stylesheet now and my brain legit needs a warm-up lap.
Tailwind makes life easier, sure… but yeah, the muscle memory theft is real.

Collapse
 
efabrizio75 profile image
Emanuele Fabrizio • Edited

Thanks for this conversation starter. I started CSS when it was a draft from the W3C (1996) but didn't get to use it really in production consistently until 2008. Why? Because the business and the users wanted pixel perfection: the web was new, and we generally moved slowly (even in Silicon Valley, yes even Yahoo!)

Then after 2012 I lost touch with technology completely, but I imagined that CSS, with the modularized specs of version 3 was going to become the way the presentation layer was always envisioned.

In 2022 I came back and tried to catch up and my take has been this: the business moves too fast for developers to think things through and work on a long term framework. Also, let's face it: front end is still a step child of the development pie, it is not taken as seriously as other areas. In 2022 I started looking at the pure CSS and wrote that as I tried to close a wide technology gap knowledge... Meanwhile I saw Bootstrap on many sites and picked that as a framework to study. Within 12 months, I heard about Tailwind's rise and looked at that too and frankly found both useful but with a steep learning curve. That's normal, however, business expectations are ABNORMAL and that leads to the rapid adoption not backed by critical analysis. It is happening everywhere in society and the majority of people opt to be silent and just tag along.

I also believe that Tailwind's utility-first approach takes style rules and convert them in inline description of how an HTML should look: doesn't take violate the "separation of concerns" between structure and presentation? Yes it does. And nobody raised it as a red flag? No, because it would have meant defeat for the hordes of businesses that relied on React but could not harmonize their components with CSS doing the presentation.

Therefore I thank you for being the person who "raised the hand ✋" on this issue for the common good 👍

Collapse
 
maxart2501 profile image
Massimo Artizzu

No naming things

Aha. You wish.
When it comes to actual projects, devs name a lot of things, because even the most fervent Tailwind aficionado will stop and give a name to a sequence a 18 utility classes that consistently apply to a button, calling it a "variant".

Maybe you name fewer things. But maybe the effort of naming thing makes you think before act and realize if the thing you're going to do makes sense or not.

You don't fight specificity.

AHA. YOU WISH.
That may be true if you limit yourself to the most basic classes - even those with custom values. But that's not true anymore when it comes to "child selectors" or when trying to use :has() or :not().

That was even more problematic in Tailwind 3, but here's the thing: a lot of projects are stuck with Tailwind 3 because switching to 4 is too much for a project that choose Tailwind because of "less maintainance".

Sure, HTML compresses well. But it still needs to be parsed.

I've never understood the compression argument. CSS compresses as much as HTML if not better.

CSS went from 45kb to 8kb with Tailwind. Great! But HTML went from 120kb to 340kb. Net increase: 183kb.

Those are just mere number. The reality is actually worse: CSS is aggresively cached by browsers. HTML is not. Now your e-commerce site must send 80 KB of HTML whenever the user clicks on a link, instead of 40.

Did the marketing mention that now you also have to install tailwind-merge, tailwind-aria, clsx, ... with their own runtime overhead? And the VS Code plugins you need to install to collapse all the class attributes when inspecting the markup and other stuff to make everything manageable? The same plugins that you don't get to install on the browser's devtools?

What about RUM reports that tell you that a certain element has been clicked... and automatically pinpoints it as a div with a dozens of classes and you have no idea where it comes from? Same thing for automatic accessibility tests? How did the marketing sell this "feature"?

Tailwind is backed by Tailwind Labs.

Problem is, it's promoted by Vercel. Vercel means Next. Next means React.

And React is, always has been and, apparently, always will be tragically bad when it comes to CSS. So much that it funneled a myriad of userland "solutions" to the cloaca of CSS-in-JS, and culminated with this Tailwind footgun that is sold like it's revolutionary but it's actually not novel at all. The concept of "atomic CSS" is ~15 years old at this point and it always failed miserably - before Tailwind. For very good reasons.

It's probably past time we ditch React too, to be honest. Its ecosystem is a complete mess. There's plenty of better alternatives anyway.

I'm not here to tell you to stop using it.

Well, I do: stop using it. It's trash. There's now single redeeming quality, except a fairly good design token that could be paralled by something way less intrusive anyway.

If this made you uncomfortable, good.

No, it did not. It made me both hopeful... and pissed, because we could have had this conversation a long time ago.

(Sorry, I won't follow you on X. We can talk on Mastodon or Bluesky if you wish.)

Collapse
 
asadalibehroz profile image
Asad Ali

I totally get this, Tailwind is amazing for speed, consistency, and not having to wrestle with specificity or naming classes, but it’s easy to see how relying on it exclusively can make us forget the fundamentals of CSS. I’ve felt the same “muscle memory” shift, I’ll instinctively think hover:bg-blue-600 before :hover { background-color: … }. I think the key is balance: use Tailwind for productivity, but keep practicing vanilla CSS, teach juniors the fundamentals first, and stay aware of the evolving platform features like container queries and cascade layers. Otherwise, we risk building an entire generation of developers who know Tailwind but don’t really know the web platform underneath.

Collapse
 
valsaven profile image
Val Saven • Edited

Tailwind won. The data proves it. The adoption proves it. If you're arguing against Tailwind in 2025, you've already lost.

Such loud words for a simple tool, not even a new paradigm =) I don’t like this kind of cultism. PHP is still being buried every year, React is decent, but Vue and Svelte have already replaced it in many projects - and tons of teams choose them, etc., etc. ...

Migrating away from Tailwind is like migrating away from jQuery was. Possible, but so painful that most people just don’t.

Yep. That’s why I honestly call it cancer. Once you use TW in a component library, you’ll have to drag it into the website that uses those components. And if it’s a legacy project - are you sure you won’t break anything with Tailwind’s built-in style reset and generic class names? I’ve personally seen cases where Tailwind broke existing logic because the site already had a global .hidden class doing visibility: hidden, and then Tailwind came in and wrecked the layout with display: none.

In short: it’s just a tool. And, as an engineer, you need to decide where it belongs and where it doesn’t. The key is not to fall into tool worship and not to force it where it causes more harm than good. Because then you end up with stuff like:

  1. A bunch of regular CSS with BEM
  2. Tailwind appears and some components or page sections are written in it
  3. Hacks start: @apply overriding original CSS or even writing regular CSS classes stuffed with @apply and Tailwind classes inside lol.
  4. Hacks with custom values if your designer has his own vision: w-[142px], etc.

I won’t even talk about how “readable” markup becomes with Tailwind. It’s just mush on the level of minified code. And since you can’t always see every scenario live - maybe there’s no such user or the feature is disabled right now - you’ll have to fix or add something based purely on code. Now be honest: what’s more readable - an element with a couple of clear BEM classes or a component/page (especially 1k+ lines of markup) stuffed with div/a/img/p/ul/li, all seasoned with Tailwind classes? With 2 themes. Across multiple breakpoints - with all those sm/md/lg. Mmm ~

Plus, one more interesting and not very pleasant point: I know several people who dislike this technology but are afraid to speak about it publicly, because others might think they’re unprofessional or against progress lol. Not sure how widespread this is, but it’s clearly unhealthy. It can create a false impression that everyone uses Tailwind, everyone more or less likes it, it’s won all the awards, taken over all the projects, etc. When in reality, things are very different.

So personally, I consider Tailwind a decent technology for its niche: prototypes or quick features where - and this is key - you probably won’t come back to later. Because developers spend most of their time reading code, not writing it. And that instant “Haha, I’m doing flex align-center brrrr” savings can bite you hard later, when you have to untangle all this in 5-6 years.

Collapse
 
designzbyoj profile image
DesignzByOJ

Idk bro... as soon as you said "cultism" I was lost, I expected better communication from an engineer, but I guess they ain't building them like they used to.

Collapse
 
cheetah100 profile image
Peter Harrison

I'm worried that developers can't write assembler anymore. It's all these high level languages like C which abstract away and hide the details of the metal. In other words Tailwind is just a abstraction over CSS which gets the job done. I don't want to be an expert in layout and graphic design; which is lucky because for the most part I'm a back end dev, so Tailwind solve 99%. For those who need the control they still have the option.

Collapse
 
maxart2501 profile image
Massimo Artizzu

If you're a backend dev you should limit yourself to use the UI components that are available to you. Period. You shouldn't touch presentational attributes if it's not your expertise. Let a frontend dev adjust the rest.

If you want to learn about frontend stuff, start from the basic. Learn CSS.
Or maybe learn accessibility patterns.
Tailwind should be the last of your concerns.

Collapse
 
shemith_mohanan_6361bb8a2 profile image
shemith mohanan

Totally agree — Tailwind makes building fast and consistent, but it’s scary how easy it is to forget real CSS. The “training wheels that never come off” part hit hard. Great reminder to keep learning the core web platform. 👏

Collapse
 
jamoralesr profile image
Jaime Morales

Twenty-one years ago, I built my first client website. Fresh developer, barely understanding CSS, just learning the basics of the web platform.

That site is still live: esmetlimitada.cl/

Same code. Zero updates. Zero maintenance. Still works perfectly.

I keep it unchanged not because the client doesn't need updates (though they don't), but because it's a time capsule. A reminder of what's possible when you build on fundamentals instead of abstractions.

Your article crystallized something I've been feeling but couldn't articulate: we're optimizing for today's productivity at the cost of tomorrow's maintainability.

I now build everything with Laravel + Tailwind. I'm 10x faster than I was writing vanilla CSS. But I wonder: will any of my current projects still be running in 2046 without updates? Or will they be legacy code requiring constant migration?

That 2004 site answers the question. The web platform is stable. Frameworks aren't.

I'm not saying abandon Tailwind—I won't. But your point about being "web developers, not Tailwind developers" matters more than people want to admit.

The platform outlasts every framework. Every. Single. Time.

Collapse
 
freelancer2020 profile image
Mostafa

Here the trick! Why you would need to remember CSS? Just let AI handle it for you - the css , accessibility and correct HTML structure, and you focus on logic and overall architecture then back again to AI when you need to debug something or test. That's all

Collapse
 
maxart2501 profile image
Massimo Artizzu

You forgot the /s at the end.

Collapse
 
brandon_pliska_0c288a6a5d profile image
Brandon Pliska

Yup. Wtf. We author now, not code by hand.

Some comments may only be visible to logged-in visitors. Sign in to view all comments.