DEV Community

Cover image for Why Tailwind CSS Might Be Hurting Your Large-Scale Projects
Gouranga Das Samrat
Gouranga Das Samrat

Posted on

Why Tailwind CSS Might Be Hurting Your Large-Scale Projects

_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

captionless image

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>
Enter fullscreen mode Exit fullscreen mode

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);
}
Enter fullscreen mode Exit fullscreen mode

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">
Enter fullscreen mode Exit fullscreen mode
// 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; }
Enter fullscreen mode Exit fullscreen mode

Compare to modern CSS:

.container {
  padding: clamp(1rem, 4vw, 3rem);
}
Enter fullscreen mode Exit fullscreen mode

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">
Enter fullscreen mode Exit fullscreen mode

Instead of using:

<Button variant="primary">
Enter fullscreen mode Exit fullscreen mode

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">
Enter fullscreen mode Exit fullscreen mode

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">
Enter fullscreen mode Exit fullscreen mode

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);
}
Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

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); 
}
Enter fullscreen mode Exit fullscreen mode

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;   
  } 
}
Enter fullscreen mode Exit fullscreen mode

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)

Collapse
 
sylwia-lask profile image
Sylwia Laskowska

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 😅

Collapse
 
xwero profile image
david duymelinck

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.