The Rise of Utility-First CSS: Tailwind CSS as an Example

2 min

1. The Difficulties of Traditional CSS Methodologies

Before Utility-First appeared, we had many excellent CSS methodologies for organizing styles, including:

  • BEM (Block, Element, Modifier): Uses the block__element--modifier naming convention to keep styles independent and maintainable.
  • OOCSS (Object-Oriented CSS): Advocates separating structure from skin and containers from content.
  • CSS-in-JS: Writes CSS directly inside JavaScript components to provide component-level style encapsulation.

These methods solve global CSS pollution and code-organization problems to some extent, but they often introduce new issues: the mental effort spent naming countless classes, the inconvenience of switching between files, and the possible runtime overhead of CSS-in-JS.

2. What Is Utility-First?

Utility-First is a CSS philosophy that provides a series of single-purpose utility classes with stable names, then builds complex UIs by combining those classes.

For example, instead of writing a .card class and defining its display, padding, and box-shadow in a CSS file, you write this directly in HTML:

<div class="block p-6 rounded-lg shadow-lg bg-white">
  <!-- ... -->
</div>

Here, block, p-6, rounded-lg, and the other utility classes each handle only one small task.

3. Tailwind CSS: The Model of Utility-First

Tailwind CSS is currently the most popular Utility-First CSS framework. It provides an extremely comprehensive set of utility classes that covers almost every commonly used CSS property.

Core advantages:

  • Extremely fast development: You barely need to leave the HTML file. By combining atomic classes, you can quickly build almost any design, greatly improving prototyping and development efficiency.
  • An enforced design system: Because every style—colors, spacing, and font sizes—comes from a predefined configuration (theme), team members can easily keep the UI consistent and avoid “magic numbers.”
  • No more naming headaches: “There are two hard things in computer science: cache invalidation and naming things.” Tailwind largely frees you from naming CSS classes.
  • Exceptional performance: During a production build, Tailwind scans your files and removes every unused CSS class through PurgeCSS (or its built-in JIT engine), so the final CSS file is usually very small.

4. “Class-Name Hell”? — A Different Perspective on the Drawbacks

The most common criticism of Tailwind is that it makes HTML bloated and difficult to read, as if we had returned to the era of “inline styles.”

<button class="py-2 px-4 font-semibold rounded-lg shadow-md text-white bg-blue-500 hover:bg-blue-700">
  Click me
</button>

This certainly takes some adjustment. Supporters, however, argue that:

  1. Style and structure are already tightly coupled, so placing them together can actually make maintenance easier.
  2. Reusable components, such as React or Vue components, can encapsulate this apparent “mess.”

For reusable combinations of styles, Tailwind provides the @apply directive:

/* in your css file */
.btn-primary {
  @apply py-2 px-4 font-semibold rounded-lg shadow-md text-white bg-blue-500 hover:bg-blue-700;
}

You can then use .btn-primary in HTML. However, Tailwind’s official recommendation is to solve reuse through componentization.

Conclusion

The success of Utility-First and Tailwind CSS marks a shift in frontend thinking about “separation of concerns”—from the separation of languages (HTML/CSS/JS) to the separation of components. Through an approach that may appear “primitive,” it solves many practical problems in modern web development and offers developers a shortcut to efficient, consistent, and high-performance UIs.