TOOLS

Tailwind CSS reopened where styles belong

Whether styles belong in a stylesheet or beside the markup was settled by convention, not by argument. Utility classes unsettled it.

Tailwind CSS logo with blue wave icon and white wordmark on black background
Utility classes unsettled a question that convention, not argument, had closed.Photo: Tailwind CSS logo with light text · Wikimedia Commons

The convention was never won

In 2003, the Web Standards Project pushed separation of concerns as orthodoxy: HTML for structure, CSS for presentation. The argument was partly practical — inline styles were hard to maintain — and partly ideological, shaped by the same decade that gave us XML. It settled into convention before most of its adopters had considered the alternatives.

Hands on a keyboard, close, screen behind showing a selector highlighted in devtools
The selector got more powerful at the same moment the stylesheet got less popular.

Tailwind CSS, first released by Adam Wathan and Steve Schoger in 2017, does not write styles into the style attribute. It writes them as utility classes — flex, pt-4, text-gray-700 — directly in the markup. The distinction matters: the browser treats them identically to any other class selector, but the authoring experience lands them squarely beside the element they affect.

That proximity is the whole argument. When a component's styles live in a separate file, changing one requires tracking the relationship between selector and element. When they live on the element itself, that relationship is immediate and local. Tailwind's bet is that co-location, not separation, is what makes styles maintainable at scale — the same bet React made about HTML, four years earlier, when JSX arrived in 2013.

— has no single correct answer, only tradeoffs that were hidden while the convention held.

The counterargument is readability: a class attribute carrying fifteen tokens is harder to scan than a named selector. Whether that cost is worth paying depends on whether your project is component-driven. In a design system with small, isolated components, a long class string stays local and therefore legible. In a templating system where the same markup renders a hundred contexts, a named class still buys more than it costs.

A screen showing a token palette beside a component, both legible
Tokens are how both camps agree on the value while still disagreeing about the file.

Tailwind's own documentation frames utility-first as a pragmatic choice, not a philosophical position. That framing is honest. The question it reopened — where do styles belong? — has no single correct answer, only tradeoffs that were hidden while the convention held.