Back to blog
Design March 8, 2025 · 7 min read

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.

Apon

Apon

Full-Stack Designer & Developer

Code editor with CSS

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 !important to 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. 🧡