Technical
Tailwind CSS: Why I Stopped Writing Custom CSS
I used to write custom CSS for every project. Carefully crafted class names, BEM naming conventions, separate stylesheet files organized by component. Then I tried Tailwind on a real project and never went back. Here is why utility-first CSS wins.
The Problem with Custom CSS
Custom CSS has a scaling problem. As your project grows, these issues compound:
- Class names become meaningless ('sidebar-inner-content-wrapper-v2')
- Specificity wars emerge and you start adding
!importanteverywhere - Dead CSS accumulates because nobody dares delete a class that might be used somewhere
- Every new feature requires new CSS that might conflict with existing styles
- Onboarding new developers means teaching them your naming conventions
What Tailwind Does Differently
Tailwind gives you small utility classes that each do one specific thing. Instead of inventing class names and writing rules, you compose utilities directly in your markup:
<!-- Custom CSS approach -->
<div class="card-container">
<h2 class="card-title">Hello</h2>
</div>
<!-- Tailwind approach -->
<div class="rounded-lg shadow-md p-6 bg-white">
<h2 class="text-xl font-bold text-gray-900">Hello</h2>
</div>The Tailwind version is longer in HTML, but you never have to open a separate CSS file, invent a class name, debug specificity conflicts, or worry about dead CSS accumulating.
The AI Connection
Tailwind works extremely well with AI coding tools. When I tell Claude Code 'make this card have rounded corners, a shadow, and more padding,' it knows exactly which classes to add. No need to create CSS rules, no need to name them, no need to figure out where to put them:
Prompt: 'Add a hover effect to the blog post cards'
AI output: className="... hover:shadow-lg transition-shadow duration-200"The AI does not need to create new CSS files or rules. It just adds utility classes. This is faster, less error-prone, and produces consistent results.
Responsive Design in Seconds
Tailwind's responsive prefixes are the feature that sold me permanently:
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
<!-- 1 column on mobile, 2 on tablet, 3 on desktop -->
</div>No media queries. No separate mobile stylesheet. No responsive mixins. Just prefixes that read like plain English: medium screens get 2 columns, large screens get 3.
Common Objections
'The HTML is ugly.' True, the class lists are long. But your CSS file does not exist. Net readability across the project is higher because all styling is colocated with the markup.
'It is not semantic.' Correct, but semantic class names solve a problem that component-based frameworks like React and Vue already solve. Your component name IS the semantic label.
'Bundle size must be huge.' Tailwind purges unused classes in production builds. The final CSS file is typically under 10KB, smaller than most custom stylesheets.
Getting Started
If you are new to Tailwind, start by converting one component from custom CSS to Tailwind utilities. You will feel the difference in development speed immediately.
See the Tailwind CSS documentation for the complete utility class reference.
RELATED READING
The Consulting Shift I Am Making In Year Two
After a year of writing and building, my consulting practice is changing shape. Shorter engagements. Sharper outcomes.
ReadThe Frontend Shift: Shipping Less JavaScript In Year Two
A year ago I reached for Next.js for everything. This year I often reach for nothing.
ReadThe Serverless Lesson I Would Write On A Sticky Note
After a year of shipping serverless projects, one rule explains most of the wins and all of the losses.
Read