Utility-first approach


Utility-first is an approach that revolutionized CSS in recent years and made Tailwind CSS extremely popular. But what is it exactly about and why does it matter?

In this lesson, we'll use a (seemingly) simple button component to explain the concept of the utility-first approach.


Although small, the buttons can cause trouble.

Compared to, for example, Bootstrap, where buttons consist of only 2 classes (e.g. .btn and .btn-primary), buttons built in Tailwind appear to be more tricky.

Why?

Because in Bootstrap classes like .btn or .btn-primary are responsible for a lot of things - padding, margins, color, hover state, active state and many more.

Abstraction layer

In such a situation, when we are unable to guess from the name itself what exactly a given class (such as .btn) does, we say that it imposes a layer of abstraction.

Of course, we can guess quite easily that the .btn class creates a button, but we can't guess from the name itself what exactly the padding, margins, color, etc. are. And although we can guess that the .btn-primary class creates primary buttons, we don't know what "primary" actually means.

So these classes are abstract.

In simple terms - if we are unable to guess from the name of the class itself the specific CSS properties that this class applies, we say that it is abstract or that it imposes a layer of abstraction.

What does the utility-first approach propose instead?

Utility-first is a CSS methodology where you build up your styles using many small, purpose-specific classes.

Traditional CSS

To illustrate it let's take an example of a button styled using traditional CSS.

First, we need to create a class .btn and apply to it desired CSS properties:

Then we can use this class in our HTML:

And this will be the result:

Tailwind CSS

The same button using a utility-first approach in Tailwind would look like this:

What catches the eye at first glance is that the Tailwind button is much more verbose.

In traditional CSS we have only one class, and in Tailwind as many as 5.

And this is just the beginning - to apply the styles for hover state, active state, disable state to our button, we will need a lot of classes.

But what do you get in return?

  • Composability: You can compose complex designs by applying many utility classes. This allows you to avoid creating unique classes for every variation of a component.
  • Direct mapping: The styling of an element is clear just by looking at the HTML. There's no need to jump to a separate CSS file to understand the styles applied.
  • Customizability: You can generate a wide array of utility classes from your configuration file in Tailwind, allowing for project-specific customization.
  • Responsive design: Tailwind provides utility classes for handling responsive designs out of the box. You can control the styles for different screen sizes using these utility classes.
  • Efficiency: You avoid bloating your CSS with unnecessary or unused styles. This approach promotes the creation of styles as they are needed, which can lead to more efficient CSS.
  • Consistency: This approach encourages consistency across a project, as it naturally creates a limited set of styles to use.

While utility-first approach might look verbose at first, it actually promotes consistency, customization, and efficiency in your styles. Also, once you get used to this approach, it can significantly speed up your development process.



John Doe

About author

Michal Szymanski

Co Founder at TW Elements and MDBootstrap / Listed in Forbes „30 under 30" / Open-source enthusiast / Dancer, nerd & book lover.

Author of hundreds of articles on programming, business, marketing and productivity. In the past, an educator working with troubled youth in orphanages and correctional facilities.