Why I ditched heavy CSS frameworks for Tailwind — and what changed
After years of fighting specificity wars and unused kilobytes, here's what finally convinced me to make the switch — and the measurable impact it had on both my workflow and my clients' performance scores.
The problem with traditional CSS frameworks
I spent three years building projects with Bootstrap and Bulma. They're great frameworks — I won't pretend otherwise. But the longer I used them, the more I found myself fighting the system rather than working with it.
Every new project started the same way: import the framework, immediately override half of it, write a mountain of custom CSS to undo the defaults, then spend 40% of dev time debugging specificity issues. The final CSS bundle was usually 80–120kb, of which maybe 15% was actually used.
"The moment you start writing
!importantto override a framework's defaults, something has gone fundamentally wrong."
What made me give Tailwind a proper shot
I'd dismissed Tailwind for a long time. The utility-class approach looked messy in the HTML, and I was convinced it would make templates unreadable. Then a client asked me to maintain an existing Tailwind project, and I had no choice.
Two weeks in, I was converted. Here's what changed my mind:
- No context switching. I stopped bouncing between HTML and CSS files. Everything is right there in the markup.
- Zero specificity wars. Utility classes are all single-level selectors. You never fight the cascade.
- Tiny final bundles. PurgeCSS (now built in) means production builds are typically 5–15kb. My average went from 110kb to 8kb.
- The design system is the config. Spacing, colours, typography — all centralised in one place.
The real-world performance impact
I rebuilt a client's marketing site using a utility-first workflow, replacing an older WordPress + Bootstrap 4 stack. The results after one month were hard to argue with:
- Lighthouse performance score: 47 → 96
- CSS bundle: 118kb → 7kb
- Time to first contentful paint: 3.8s → 0.9s
- Bounce rate: -22%
Why this site still runs on Bootstrap
Not every project needs the same tool. This portfolio runs on Bootstrap 5 because it ships a mature component library, sensible defaults, and built-in dark mode support out of the box — which means less time hand-rolling primitives and more time on content and interaction detail. For a personal site with a handful of pages, that trade-off makes sense; for a large product surface with a fully custom design system, a utility-first approach usually wins.
What I still miss from utility-first workflows
It's not all one-directional. A few things I still reach for a component framework to get for free:
- Pre-built complex components like modals, dropdowns, and offcanvas menus
- Consistent form validation styling out of the box
- An opinionated grid system that's fast to reach for on content-heavy pages
The right call depends on the project: how many pages, how custom the design needs to be, and how much of the interactivity layer you want a framework to own for you.
My recommendation
If you're building anything highly custom — a SaaS product with a distinct visual identity — a utility-first approach gives you the most control. The learning curve is about a week; after that you'll ship faster than before.
If you need a content site, a portfolio, or a project with a small team that benefits from consistent, well-tested components, Bootstrap remains a genuinely solid choice. Use the right tool for the job.
If this was helpful, share it with a developer friend weighing the same decision. 🧡