
Tailwind won. In 2026 it is the default answer to "how should I style this," it moved its whole config into CSS with @theme, and the tooling is genuinely good. So when I built my site, the sensible move was to reach for it.
I didn't. I hand-rolled my own design system in plain CSS custom properties. No Tailwind, no utility classes, just a tokens file and real stylesheets. I want to give you the honest scorecard, both columns, because "just use Tailwind" and "utility CSS is bad" are both lazy takes.
What I actually built
My whole system is a set of CSS variables. Colors, spacing, typography, radius, all defined once as tokens and referenced everywhere. Dark mode is a data-theme="dark" attribute on the root that swaps the token values, paired with a small ThemeContext that remembers the choice and falls back to the system preference. Fonts are self-hosted and declared in one place. That is the entire foundation.
The interesting part is the color tokens, because that is where a real design system earns its keep. I have separate token families for things that look similar but behave differently. There is an "on-primary" family for text and borders that sit on my primary-colored surfaces, kept apart from the normal text tokens, because my primary color flips lighter in dark mode and anything painted on it has to flip with it. I split error text from error fill, because a color dark enough to hold white text on top is too dark to read as error text on a light surface. These are not things a utility framework hands you. They are decisions you make once you actually care about contrast in both themes.
What hand-rolling cost me
Now the honest part, because it was not free.
Tailwind gives you a consistent spacing scale, a responsive system, and state variants for nothing. I re-implemented the pieces of that I needed, by hand, and I owned every bug in them. And there were bugs. I had a legacy stylesheet quietly shadowing my newer tokenized styles through CSS specificity, so changes "didn't apply" for reasons that took real digging to find. I had position: sticky silently break because an ancestor set overflow-x: hidden, which turns the other axis into a scroll container. Tailwind would not have saved me from the sticky bug, but a stricter system would have made the shadowing one harder to create in the first place.
There is also the consistency tax. Utility classes make it hard to drift, because everyone pulls from the same scale. My hand-rolled setup let me drift. At one point I had management pages carrying a totally different color palette from the rest of the admin panel, because nothing forced them to agree. I had to go back and unify it on purpose. Tailwind makes that kind of drift much harder by default, and that is a real advantage on a team.
Why I still think it was right, for me
Here is the thing. My constraints are not a team's constraints. I am one person, the codebase is small, and one of my actual goals is to understand CSS deeply, not to abstract it away. Hand-rolling forced me to learn the cascade, custom properties, color-mix, container queries, and how theming really works. That knowledge is the point, not a side effect.
And modern CSS has quietly removed a lot of Tailwind's original reason to exist. Custom properties, @property, cascade layers, container queries, color-mix. The platform now does natively most of what made a utility framework feel necessary five years ago. Writing plain CSS in 2026 is a much nicer experience than the one people are remembering when they say never write your own CSS.
The actual recommendation
So who should do what. If you are on a team, shipping fast, and you need many hands to stay consistent without a design review on every PR, use Tailwind. It is the right tool for that, and fighting it is a waste of energy. If you are solo, your codebase is small, and you want full control plus a real understanding of how your styles work, hand-rolling with modern CSS custom properties is not the mistake people say it is. It is a legitimate choice with its own payoff.
I picked control and learning over speed and enforced consistency, because that matched my project. I paid for it with a few self-inflicted bugs and one palette cleanup. I would make the same trade again, on this project, with clear eyes about what it cost.
The lazy version of this debate is "Tailwind good" or "Tailwind bad." The real answer is that they optimize for different things, and you should know which one you actually need before you reach for either.