← All posts

The CSS I Rewrote After Learning Tailwind

Not a hot take post — just an honest look at what utility-first changed in how I reason about styles.

Jul 25, 20261 min read191 words

I resisted Tailwind for two years. My reasoning was principled: separation of concerns, DRY styles, semantic class names. All the right arguments. Then I joined a team using it and spent a month being wrong about everything.

The thing that changed my mind wasn't the developer experience hype. It was reading a component and immediately knowing exactly how it looked without jumping to a CSS file. Co-location of concerns, not separation.

What I actually changed

Most of my old patterns mapped cleanly. BEM blocks became components. Modifiers became conditional classes. The one pattern I genuinely miss is complex selectors — :has(), sibling combinators, attribute selectors — which feel awkward as arbitrary variants.

What Tailwind doesn't fix

Design tokens. Tailwind gives you a scale but not a system. On any real project I end up building a tokens.ts anyway — spacing, color roles, type scales — and wiring them into the config. At that point, the utility classes are just a shorthand for a system you still had to design.

The framework is a tool, not a substitute for design thinking. I've seen beautiful Tailwind codebases and nightmarish ones. The difference was always the designer, not the framework.

csstailwindfrontend