← Back to context

Comment by spankalee

2 days ago

I think it'd be better for AI and web dev if AIs generated real CSS instead.

The supposed difficulty of tracking from elements to classes to rulesets is something that AIs can easily handle, and being able to change a ruleset once and have the update apply to all use sites is really good for AI-driven changes.

Plus, humans and AIs won't have to wait for Tailwind to adopt new CSS features as they are added. If the AI can read MDN, it can use the feature.

I really don’t understand this idea that seems to be prevalent to let the LLM generate everything from scratch instead of using existing battle tested frameworks. Be it for css or backend code.

Good modular design of software and separation of concern are still important for debugging and lifecycle. For (instructing) the llm it will also be easier if it uses frameworks as the resulting code of the project itself will remain smaller, reducing the context for both llm and human.

  • CSS simply doesn't need a framework - there's no "from scratch". For humans or LLM authors.

    Tailwind is a lot of overhead conceptually and tooling wise to just not have to write classnames, and it's actually anti-modular.

    • That's not the full picture.

      If you're a senior CSS developer you will invariably reach a point of using "object oriented CSS" which is where you combine classes to an effect.

      At that point you're not far off Tailwind. TW just took it all the way.

  • Supply chain risk is real. Granted in CSS it’s probably less of a concern than in code, but it cannot be denied. LLMs make the proposition of supply chain reduction not irrational at the very least.

I’ve had zero problems getting Claude to generate CSS.

I generally ask for the following, from scratch for each project:

- A theme file full of variables (if you squint this actually looks a bit like Tailwind)

- A file containing global styles, mostly semantic, rather than just piles of classes

- Specific, per component styles (I often use Svelte so this is easy as they live in the component files and are automatically scoped to the component)

IMO there’s even less need for Tailwind with AI than there was before.

When I see people talking about how good AI is with Tailwind it just feels like they’re lazily copying each other without even trying to avoid unnecessary complexity.

I'm not a fan of Tailwind, but I can see that it's probably reasonable for code gen to be able to write / extend projects that use Tailwind, since it's in pretty widespread use. For a new project, maybe it could ask if you want to use Tailwind or just keep things vanilla?

Tailwind is almost too simple to bother using an LLM for. There’s no reason to introduce high-level abstractions (your “real” CSS, I imagine) that make the code more complicated, unless you have some clever methodology.

AI is great at any styling solution via system prompt + established patterns in codebase. Tailwind is just slightly more convenient since it's consistent and very popular.

Totally agree with this, and I think it's what will likely happen. IMO Tailwind got to the point where you are adding dozens of classes to the tag and it gets a little unwieldy. There are some options to get around it but if AI just does't need it it's even better.

There's nothing stopping you from requesting the AI write bare CSS. They're pretty decent at that too. And feed back screencaps, ask it to fix anything that's wrong, and five iterations later you have what you want. Just like a developer.

Bonus point: It'll appreciate one of those "CSS is awesome" mugs, too.

I don't really like Tailwind, but it's a really good fit for LLM tools because there's basically no context needed like you get with normal CSS inheritance, etc. What you see is what you get.

The thing is LLM generate token by token and if you have to write entire css before writing the html, the quality could be worse.

  • You could prompt the LLM to define styling using inline `style` attributes; and then, once you've got a page that looks good, prompt it to go back and factor those out into a stylesheet with semantic styles, trading the style attributes for sets of class attributes.

    Or you could tell the LLM that while prototyping, it should define the CSS "just in time" before/after each part of the HTML, by generating inline <script>s that embed CSS stanzas as string literals, and which immediately inject those into the document using CSSStyleSheet.insertRule(). (This can, again, be cleaned up afterward.)

    Or, you can keep your CSS and your HTML separate, but also keep an internal documentation file (a "style guide") that describes how and when to use the CSS classes defined in the stylesheet. This is your in-context equivalent to the knowledge the LLM already has burned-in from training on the Tailwind docs site. Then, in your coding agent's instructions, you can tell it that when writing HTML, it should refer to the "style guide", rather than trying to reverse-engineer the usage of the styles from their implementation in CSS.

The problem is training data. How many modern web sites use raw CSS?

  • Enough that in my experience Claude is great at it and there’s even less justification for Tailwind if you’re using AI.

Counter-argument: the cascade in CSS was a massive design mistake and it shows even more in this particular case.

With LLM-assisted development you spend more time reading and reviewing the generated code. The cascade in styles is nowhere near as readily apparent as something like Tailwind.

  • I haven't seen cascades be a problem since the days of monolithic, app-wide stylesheets, and no project I personally know of works that way anymore.

    Just about everyone uses component-specific styles with a limited set of selectors where there are very few collisions per property, and pretty clear specificity winners when there are.

    If the alternative to the cascade is that you have to repeat granular style choices on every single element, I'll take the cascade every time.

  • If you're arguing down that route, LLMs can bulk-apply style attributes exactly where they're needed. Every element precisely described, no need for CSS and style-sheets at all.

    • And then you'd wind up with a needlessly noisy approach, and then you will reach for Tailwind to do basically the same thing but in a more terse manner. ;P