From Tailwind Skeptic to Advocate - A CSS Journey
css tailwind frontend web-developmentHow I went from hating utility-first CSS to becoming its biggest champion
The CSS Purist
"Tailwind is just inline styles with extra steps."
That was my smug response whenever someone suggested we try Tailwind CSS for our projects. As the lead frontend developer at a mid-sized agency, I considered myself a CSS purist. I had carefully crafted my approach over years:
- Well-organized SCSS files with clear imports
- BEM methodology for class naming
- Custom mixins for responsive design
- Variables for consistent theming
My system worked. It was methodical, organized, and—most importantly—it followed separation of concerns. HTML was for structure, CSS for styling, and JavaScript for behavior. Mixing them felt wrong, and Tailwind's utility-first approach seemed like a step backward in web development.
So when our new developer, fresh out of a bootcamp, suggested we use Tailwind for our next project, I almost laughed out loud.
"We're professionals here," I explained condescendingly. "We write proper CSS."
Little did I know how wrong I was, and how much that decision would cost us.
The Breaking Point
Six months later, our team was drowning in CSS. We were building a complex web application with dozens of components, multiple themes, and responsive layouts. Our carefully organized system was falling apart:
- Our main CSS bundle had grown to over 500KB
- Specificity conflicts were causing unexpected overrides
- New developers spent days just understanding our CSS architecture
- Making changes to shared components required testing the entire application
The final straw came during a critical client presentation. We were demonstrating a new feature, and suddenly the layout broke. A CSS change for an unrelated component had cascaded and affected our demo page. The client was not impressed.
That night, I stayed late at the office, staring at our CSS codebase. Despite our best practices and organization, we had created a monster. The cascade, which I had once championed as CSS's greatest feature, had become our biggest problem.
Out of desperation, I decided to try what I had been resisting for so long. "Let me build just one component with Tailwind," I thought. "Just to see what all the fuss is about."
The Experiment
I chose a relatively complex component for my experiment: a pricing card with hover effects, responsive behavior, and multiple themes. In our existing system, this would require:
- Creating a new SCSS file
- Adding BEM classes
- Writing media queries
- Adding theme variations
- Importing the styles into our main stylesheet
With Tailwind, I simply wrote the HTML with utility classes:
<div
class="rounded-lg shadow-lg overflow-hidden transform transition-transform hover:scale-105"
>
<div class="bg-gradient-to-r from-blue-500 to-purple-600 p-6">
<h3 class="text-xl font-bold text-white">Premium Plan</h3>
<p class="text-white/80 mt-1">For growing businesses</p>
<p class="text-4xl font-bold text-white mt-4">
$49<span class="text-lg">/mo</span>
</p>
</div>
<div class="bg-white p-6 dark:bg-gray-800">
<ul class="space-y-3">
<li class="flex items-center">
<svg
class="h-5 w-5 text-green-500"
fill="currentColor"
viewBox="0 0 20 20"
>
<path
d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z"
></path>
</svg>
<span class="ml-2 text-gray-700 dark:text-gray-300"
>Unlimited projects</span
>
</li>
<!-- More list items -->
</ul>
<button
class="mt-6 w-full bg-gradient-to-r from-blue-500 to-purple-600 py-2 px-4 rounded text-white font-medium hover:from-blue-600 hover:to-purple-700 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-opacity-50 transition-colors"
>
Get Started
</button>
</div>
</div>
I was surprised by how quickly I could build the component. No context switching between files, no coming up with class names, and most importantly, no worrying about how these styles might affect other components.
But the real test came when I needed to make changes. In our old system, even small adjustments could lead to unexpected consequences. With Tailwind, I could modify the component with confidence, knowing my changes were scoped to this component alone.
The Revelation
After a few days of experimenting with Tailwind, I had several realizations that completely changed my perspective:
-
Naming things is hard. Coming up with meaningful, consistent class names is a surprisingly difficult cognitive load that Tailwind eliminates.
-
The cascade is both powerful and dangerous. CSS's global nature makes it easy to accidentally affect elements you didn't intend to change.
-
Separation of concerns isn't always beneficial. Having styles next to markup actually improves maintainability for components.
-
CSS files never stop growing. Traditional CSS tends to grow indefinitely because developers are afraid to remove rules that might be used somewhere.
-
Consistency is built into Tailwind. The predefined spacing, color, and typography scales forced me to be more consistent than I ever was with custom CSS.
The most surprising benefit was speed. I could build components significantly faster with Tailwind than with our traditional approach. No more switching between files, no more searching for the right place to add a new style, and no more worrying about naming conflicts.
The Pitch
Armed with my new insights, I called a team meeting to propose something that would have been unthinkable just weeks before: moving our entire project to Tailwind CSS.
I was expecting resistance, especially from the other senior developers. Instead, I found curiosity and openness. Our CSS problems were affecting everyone, and they were willing to try something new if it could help.
I presented a plan for a gradual migration:
- Set up Tailwind alongside our existing CSS
- Build all new components with Tailwind
- Gradually refactor existing components when we needed to make changes
- Measure the impact on bundle size, development speed, and bug reports
A week later, we started our first full-team project with Tailwind CSS.
The Migration
Moving to Tailwind wasn't without challenges. The learning curve was steeper than I expected, especially for developers who weren't as familiar with CSS properties. We had to develop new patterns and conventions:
- Extraction for repetition: When the same set of utilities was used in multiple places, we extracted them into Tailwind components.
@layer components {
.btn-primary {
@apply px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-600 transition-colors;
}
}
- Custom plugins for brand styles: We created custom Tailwind plugins to incorporate our client's brand elements.
// tailwind.config.js
const plugin = require("tailwindcss/plugin");
module.exports = {
// ...
plugins: [
plugin(function ({ addComponents, theme }) {
const brandComponents = {
".brand-card": {
backgroundColor: theme("colors.white"),
borderRadius: theme("borderRadius.lg"),
boxShadow: theme("boxShadow.md"),
overflow: "hidden"
}
};
addComponents(brandComponents);
})
]
};
- Responsive variants: We established conventions for responsive design, using Tailwind's responsive prefixes consistently.
<div class="text-sm md:text-base lg:text-lg">
Responsive text that scales with screen size
</div>
The most difficult part was changing our mindset. We had to stop thinking about global styles and instead focus on composing elements with utility classes. This was especially challenging for our designers, who were used to creating pixel-perfect mockups that we would then implement with custom CSS.
The Unexpected Benefits
After three months of using Tailwind, we noticed several unexpected benefits:
-
Our CSS bundle size decreased by 71%. Tailwind's purge feature eliminated all unused styles, resulting in a much smaller CSS file than our previous approach.
-
Design consistency improved dramatically. Because Tailwind encourages using predefined values for spacing, colors, and typography, our interfaces became more consistent without explicit effort.
-
Designer-developer collaboration improved. Designers started to think in terms of the design system that Tailwind enforced, leading to designs that were easier to implement.
-
Onboarding new developers became simpler. New team members could be productive much more quickly because they didn't need to learn our custom CSS architecture.
-
Performance bugfixes decreased by 68%. CSS-related bugs like z-index issues, overflow problems, and specificity conflicts became far less common.
But perhaps the most significant benefit was psychological. Our team no longer dreaded making CSS changes. The fear of breaking something unrelated had been eliminated, which led to more confident and rapid development.
The Conversion of a Skeptic
Today, two years after that first experiment, I can confidently say that Tailwind CSS has transformed how our team builds for the web. As the once-skeptical CSS purist, I now find myself advocating for Tailwind in every new project.
My journey from critic to advocate taught me several valuable lessons:
-
Strong opinions should be weakly held. My certainty about the "right way" to write CSS was limiting my growth as a developer.
-
Productivity often trumps purity. While I still appreciate the elegance of well-organized CSS, the practical benefits of Tailwind outweigh the theoretical advantages of strict separation of concerns.
-
Tools evolve for a reason. Tailwind didn't gain popularity because developers are lazy or don't understand CSS—it gained traction because it solves real problems that traditional approaches struggle with.
-
Pragmatism beats purism. The best approach isn't always the most theoretically pure one, but the one that helps your team ship better products more efficiently.
If you've been resisting Tailwind CSS because of deeply held beliefs about how CSS should be written, I encourage you to set aside those opinions for just one project. Build something real with it, experience the workflow, and then decide.
You might find yourself, like me, becoming an advocate for the very thing you once criticized. And in the fast-evolving world of web development, that's not a bad thing—it's growth.