Skip to content

CSS Utility Classes: How To Use Them Effectively

Published on

Utility classes are meant to do only one thing, and do it well. They are designed to be simple, composable and re-usable, allowing for easy and fast development.

While a CSS system based on utility classes alone is not desirable, having a set of utility classes that allow you to quickly put together templates is great.

So where do we draw the line? How do we decide if a utility class is the right approach in any given situation?

Utility classes should be the exception, not the rule. Only consider using a utility class if the rule you want to apply is:

  • Exceptional & Specific: “In this particular case, I want this card to have a larger top margin”. If you find yourself consistently employing the utility class across many instances of the same component, you should consider either using a scope class (if it occurs only inside a specific context) or introducing a new variant to your component.
  • Optional: Could it be safely removed without breaking the component’s appearance? Using the previous example, it makes sense to employ a utility class to give your card a larger top margin, but not to give it a white background color or a black box shadow (non-optional, component-specific styling).
  • Definite: You don’t expect this rule to be overridden by any other rule in your stylesheet (One exception to this rule is responsive utilities, where you have multiple utility classes applied at different breakpoints). All of your utility classes should carry an “!important” declaration to force immutability.

Common Use Cases

I find utility classes really helpful for:

  • Margin/padding
  • Text (colors, size, styles)
  • Common Background Colors
  • Hiding/Showing stuff
  • Display (block, inline-block)

However, you still have to consider each case separately using the guidelines above. Just because you have a utility class for something, it doesn’t mean it’s the right approach for that particular case.

Naming utility classes

To separate utility classes from component classes, it’s good to namespace them. I use the .u- namespace.

You can also shorthand most properties for faster coding. Here are a couple I use:

  • p/m for margin/padding
  • t/r/l/b for top/right/left/bottom
  • v/h for vertical/horizontal
  • bg for background

BEM and utility classes

I’ve recently seen an example of spacing utility classes named like this:

<div class="u-mt--large">
  <p>Content</p>
</div>

Where mt means margin-top and large is a variable that means 32px. In BEM, the two dashes (also known as the modifier notation) imply that this class .u-mt--large is a modifier of the original .u-mt class.

Modifier classes are not meant to be independent. And that means the original class should always be included. The proper BEM-style way of doing it would be:

<div class="u-mt u-mt--large">
  <p>Content</p>
</div>

This doesn’t really make sense. Utility classes are meant to be independent.

Also, not only I’m making it much longer than it needs to be (two classes vs just one). I’m overriding the first class with another.

The solution I’ve found is to remove the modifier notation and camel case the classname for better readability:

<div class="u-mtLarge">
  <p>Content</p>
</div>

Of course, you could also do:

<div class="u-mt-large">
  <p>Content</p>
</div>

Responsive Utilities

If you need to employ different utility classes across different screen sizes, you can use the responsive suffix @<breakpoint>:

<div class="u-mt u-mtLarge@medium">
  <p>Content</p>
</div>

“Won’t all these utility classes bloat my CSS?”

Utility classes should never be the bulk of your system. However, it’s easy to over-do them, specially when introducing breakpoints into the mix. My advice:

  • Always be refactoring. Make it a habit to check for cases where rules (and combinations of rules) should be formalized into a new component or a variant of an existing one.
  • Consider post-processing your CSS with a tool like UnCSS. This way you can have the best of both worlds: Develop quickly with utility classes, and avoid bloat by removing the ones you don’t use from your production stylesheet.

Join my newsletter and get articles like this delivered straight into your inbox.