Comment by CSSer
9 hours ago
Tailwind didn't win for either of these reasons (setting aside any personal positive/negative feelings I have about it). It won (in LLMs) because that's how the ML model works. The training data places the HTML and the styling info together. There's an extremely high signal to noise ratio because of that. You're going to get much fewer tokens that have random styles in it and require several fewer (or maybe even no) thought loops to get working styles. The surface API of selectors is also large and complex. Tailwind utility classes are not. They're either present on an element or not, and it's often the case that supporting classnames for the UI goal are present in close proximity on sibling, parent, or child elements. Even with vast amounts and multiple decades of more CSS to compare against in the training data, I suspect this is the case. Plus, the information is just spread more thinly and more flexible in terms of organization in a stylesheet. The result is you get lots of extra style rules that you didn't need/want and it's harder to one-shot or even few-shot any style implementation. If I'm even remotely right about this, it worth considering this impact in many other languages and applications. I've found the adverse effect to be reduced slightly as models/agents have improved but I feel it's still very much present. It's totally possible to structure data in a way that makes it easier to train on.
There's also a reasonable alignment between Tailwind's original goal (if not an explicit one) of minimizing characters typed, and a goal held by subscription-model coding agents to minimize the number of generated tokens to reach a working solution.
But as much as this makes sense, I miss the days of meaningful class names and standalone (S)CSS. Done well, with BEM and the like, it creates a semantically meaningful "plugin infrastructure" on the frontend, where you write simple CSS scripts to play with tweaks, and those overrides can eventually become code, without needing to target "the second x within the third y of the z."
Not to mention that components become more easily scriptable as well. A component running on a production website becomes hackable in the same vein of why this is called Hacker News. And in trying to minimize tokens on greenfield code generation, we've lost that hackability, in a real way.
I'd recommend: tell your AGENTS.md to include meaningful classnames, even if not relevant to styling, in generated code. If you have a configurability system that lets you plug in CSS overrides or custom scripts, make the data from those configurations searchable by the LLM as well. Now you have all the tools you need to make your site deeply customizable, particularly when delivering private-labeled solutions to partners. It's far easier to build this in early, when you have context on the business meaning of every div, rather than later on. Somewhere, a GPU may sigh at generating a few extra tokens, but it's worthwhile.