process · 2024-07-02 · 5 min
Why I still write CSS by hand
Utility classes solve a real problem. They don't solve the problem of taste.
Tailwind earned its place. The day I stopped naming .CardWrapperInner__title--large was the day I shipped twice as much UI. I'm not going back.
The moment it broke down
Somewhere between the third and fourth time I wrote text-sm font-medium tracking-tight leading-snug in a row, I noticed I was no longer designing. I was assembling.
Bilingual codebases
So I write CSS again — not instead of utilities, but alongside them. The design system layer.
@utility grain {
position: relative;
&::after {
content: "";
position: fixed; inset: 0;
background-image: url("data:image/svg+xml;utf8,...");
opacity: 0.05;
mix-blend-mode: overlay;
}
}Tokens, custom properties, a handful of named utilities for the things that recur with intent: .grain, .reveal-on-scroll, .marquee. The utility soup handles the noise. The CSS layer holds the taste.
The codebase ends up bilingual. That's fine. Good design systems usually are.