Skip to content

Formalize utility-first css preference

Proposal

Let's formalize a "utility-first" CSS preference (this is different than "utility-only"):

  1. Start with utility classes.
  2. If composing utility classes into a component class removes code duplication and encapsulates a clear responsibility, do it.

Why?

  • "utility-first" encourages the organic growth of component classes.
  • It prevents the creation of one off not reusable classes.
  • It keeps component classes cohesive, since they can be combined with other utility classes.
  • It also encourages the creation of design-centered classes (e.g. button, alert, input), rather than domain-centered classes (e.g. security-report-widget, commit-header-icon).

Inspiration:

Description

Throughout all Frontend projects, it is unclear when to prefer utility classes vs. component classes. Let's formalize our preference and add it to our FE documentation.

What are utility classes?

.d-flex.prepend-top-default.append-bottom-default

Bootstrap4 introduced many utility classes that each apply a single CSS rule. We've also adopted this pattern and created some custom utility classes. These are helpful for quickly overriding styles that are highly specific.

What are component classes?

.component-header

This is the common practice of creating CSS classes that encapsulate a logical set of rules.

Analysis

What are our goals?

  • Increase maintainability
  • Reduce CSS bloat

Advantages of utility classes:

  • Prevents the need for one-off CSS classes that are never reused

Disadvantages of utility classes:

  • Harder to read
  • Harder to edit in the browser inspector
  • The set of utility classes applied to an element is not reusable (although the Vue component itself is reusable)

Advantages of component classes:

  • Easier to read
  • Easier to edit in the browser inspector
  • Reusable
  • Semantically describes the HTML element

Disadvantages of component classes:

  • When reused in the wrong place, it can cause coupling of unrelated elements, hurting modifiability.
  • Naming of these classes can easily be inconsistent and unintuitive (e.g. wrapper, container, content, etc.

Conclusion

There is nothing keeping us from doing both, but using either inappropriately leads to a brittle style sheet. utility-first is a pragmatic way to ensure we are creating the right kind of component classes.

Related Resources

Edited by Paul Slaughter