Why I switched back to plain CSS

I spent two years writing utility-first CSS. Tailwind, specifically. And for a while, it was great. Fast to prototype, easy to reason about, zero naming decisions. But somewhere along the way, I started missing something I couldn't quite name.

It took me a while to figure out what it was: authorship. When every element is a string of px-4 py-2 bg-gray-900 text-sm, the stylesheet stops being a design artifact and becomes a configuration file. I wanted to write CSS again, not configure it.

What I missed

  • Custom properties that tell a story — --bg, --text-muted, --border
  • Selectors that describe relationships, not just elements
  • Media queries that feel considered, not bolted on
    • Tailwind's sm: / md: breakpoints felt arbitrary for my designs
    • I wanted breakpoints based on content, not device categories
  • A single file I could read top-to-bottom and understand the entire design system

What I don't miss

I'm not going to pretend everything about vanilla CSS is better. There are genuine trade-offs:

  • Naming things is hard. You spend time thinking about .card-header vs .card-top
  • The cascade can bite you if you're not careful with specificity
  • Prototyping is slower — you have to write actual rules, not just add classes

My current setup

Here's what I use now for every project:

  • One style.css file with CSS custom properties for theming
  • Minimal reset (box-sizing, margin, padding)
  • Semantic class names that describe purpose, not appearance
  • No build step. No PostCSS. No purging. Just CSS

The result is a stylesheet I can read like a document. Every section maps to a part of the page. Every variable name tells me what it controls. It's not the fastest way to work, but it's the most intentional way to work. And for my projects, that matters more.

Related

Plain CSS isn't trendy. It's not going to get you likes on Twitter. But it works, it lasts, and it forces you to understand what you're building. That's enough for me.