_A honest discussion about the trade-offs nobody
Introduction
After 5 years of using Tailwind CSS in production, I’ve learned some hard lessons about utility-first CSS at scale. This isn’t another “Tailwind bad” rant — it’s an honest conversation about when this popular framework starts showing its limitations.
Disclaimer: I don’t have exact metrics to share (NDAs exist), but I’ll walk you through the real patterns and problems we encountered.
The Good: Why We Chose Tailwind
Let’s start with credit where it’s due. Tailwind CSS delivers on many promises:
- Rapid prototyping — Building UIs has never been faster
- No context switching — Stay in your HTML/JSX files
- Consistent spacing — The design system is built-in
- Small learning curve — New developers can contribute immediately
For the first few months, it felt revolutionary.
The Reality Check: When Scale Hits
1. The Readability Problem
Here’s what our components started looking like:
// A real card component from our codebase
<article className="relative flex flex-col min-w-0 rounded-lg break-words border border-gray-200 bg-white shadow-sm dark:border-gray-700 dark:bg-gray-800 md:flex-row md:items-center md:justify-between hover:shadow-lg transition-shadow duration-200">
<div className="flex-1 p-4 md:p-6 lg:p-8">
<h2 className="text-lg md:text-xl lg:text-2xl font-semibold text-gray-900 dark:text-white mb-2">
{title}
</h2>
<p className="text-sm md:textbase text-gray-600 dark:text-gray-300 line-clamp-3">
{description}
</p>
</div>
</article>
The problem?
- Can you tell what this component does at a glance?
- How would you modify just the desktop layout?
- Where does the component styling end and utility classes begin?
2. The Maintenance Challenge
Consider this scenario we faced last fewmonths:
Design team: “We need to update all card shadows to be more subtle”
With Tailwind: Search for shadow-sm, shadow-lg, hover:shadow-xl across:
- Components
- Templates
- Random utility combinations
- Third-party components we customized
With CSS Modules: Update one variable:
:root {
--card-shadow: 0 1px 3px rgba(0, 0, 0, 0.08);
}
3. The Bundle Size Discussion
While Tailwind’s PurgeCSS is impressive, here’s what people don’t discuss:
// What your HTML looks like
<div className="p-4 md:p-6 lg:p-8 xl:p-10 2xl:p-12">
// What CSS gets generated (simplified)
.p-4 { padding: 1rem; }
.md\:p-6 { padding: 1.5rem; }
.lg\:p-8 { padding: 2rem; }
.xl\:p-10 { padding: 2.5rem; }
.2xl\:p-12 { padding: 3rem; }
Compare to modern CSS:
.container {
padding: clamp(1rem, 4vw, 3rem);
}
One line vs five classes. Multiply this by every responsive property in your app.
The Patterns That Hurt Us
Anti-Pattern 1: The Copy-Paste Culture
New developers would copy this:
<button className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded">
Instead of using:
<Button variant="primary">
Result: Inconsistent button implementations everywhere
Anti-Pattern 2: The Component Sprawl
// What we ended up with across different files
<div className="bg-white p-6 rounded-lg shadow-md">
<div className="bg-white p-4 rounded shadow-sm">
<div className="bg-white p-8 rounded-xl shadow-lg">
Result: Three slightly different “card” components that should have been one reusable <Card> component.
Anti-Pattern 3: The Responsive Madness
<div className="text-sm md:text-base lg:text-lg xl:text-xl 2xl:text-2xl p-2 md:p-4 lg:p-6 xl:p-8 2xl:p-10 m-1 md:m-2 lg:m-3 xl:m-4 2xl:m-5">
Compare this to modern CSS
.responsive-text {
font-size: clamp(0.875rem, 2.5vw, 1.5rem);
padding: clamp(0.5rem, 4vw, 2.5rem);
margin: clamp(0.25rem, 1vw, 1.25rem);
}
The Real Numbers: What UK Developers Are Saying
------------------------to---------------------
Based on recent survey data, the UK was among the top three countries participating in developer surveys, alongside the USA and Germany State of CSS 2024 Survey Now Open — WP Tavern. Here’s what the data reveals:
Usage Reality Check: While 75% usage seems impressive, only 50% of survey respondents actually answered the Tailwind question.
This means real usage is closer to 37.5% of all developers 🔍 Going through the “State of CSS” results… • Josh W. Comeau — significant, but not the overwhelming majority some claim.
The Maintenance Problem is Real: As one developer put it:
“I really tried to like Tailwind. And I understand what it does and its benefits. But ease of code readability, to me anyway, is #1. I am not used to having my HTML/JSX/whatever filled to the brim with a million classes. It’s unbelievably messy.”
When Tailwind Actually Works Well
Let’s be fair — Tailwind isn’t always the wrong choice:
- Rapid prototyping — For hackathons and proof-of-concepts
- Small teams with limited CSS knowledge
- Projects with simple design systems
- Marketing sites with minimal maintenance needs
The key insight: It’s perfect for projects compatible with uncomplicated CSS and low maintenance, and it’s ideal for front-end teams with little knowledge of CSS or limited resources allocated for CSS architecture.
My solution: A Hybrid Approach
After few years of pure Tailwind, here’s what we’re moving towards:
Component-First Architecture
// Instead of this Tailwind mess
<button className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded focus:outline-none focus:shadow-outline">
// We use this <Button variant="primary">Submit</Button>
CSS Custom Properties for Theming
:root { --color-primary: #3b82f6;
--spacing-card: clamp(1rem, 4vw, 2rem);
--shadow-card: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
}
Modern CSS Features
.container {
container-type: inline-size;
padding: clamp(1rem, 5vw, 3rem);
}
.card { padding: var(--spacing-card);
box-shadow: var(--shadow-card);
}
@container (min-width: 768px) {
.card-content {
display: grid; grid-template-columns: 1fr 2fr; gap: 2rem;
}
}
The Final Verdict
Tailwind CSS isn’t inherently bad — it’s a tool that works brilliantly for specific use cases. However, the scenario where “what once felt like a productivity boost now feels like technical debt” is all too common when developers adopt Tailwind without established patterns for large-scale implementations Best Practices for Using Tailwind CSS in Large Projects — Wisp CMS.
The hard truth? For large-scale projects, traditional CSS architecture often provides better long-term maintainability, performance, and developer experience.
Before choosing Tailwind, ask yourself:
- Will this project need significant design updates?
- Do we have senior CSS developers on the team?
- Are we building a design system that will be used across multiple projects?
- Do we need fine-grained control over our styles?
If you answered “yes” to any of these, consider modern CSS approaches instead.
Remember: The goal isn’t to use the trendiest tool — it’s to build maintainable, performant websites that serve your users well.
What’s been your experience with Tailwind at scale? Have you faced similar challenges, or found solutions that work? I’d love to hear your thoughts in the comments below.

Top comments (2)
Great observation! I feel the same – Tailwind is amazing for prototyping, but not necessarily for large projects. And who loved it the most? Backend devs who occasionally had to do something on the frontend 😅
I think it is more of a frontend FOMO thing like SPA or micro frontends.
People see it used in one situation and then they want to use it everywhere.
I still don't understand why people are drawn to a utility classes only framework. Utility classes are not bad but this is the equivalent of using a, b and c to name your variables. You don't create context, it is easy to make mistakes, and you are copying things all over the code.
Bootstrap has flaws, but when CSS got better they incorporated the new features. I see that that less with Tailwind. It looks like they are more concerned with improving the utility classes.
With every tool people create you have to ask yourself, do I need this for my application.