Episode 1 — Fundamentals / 1.10 — CSS Architecture and Project Structure

1.10.c — Utility vs Component Classes

In one sentence: Utility classes apply one declaration each and are composed in HTML; component classes bundle many declarations behind a semantic name — and the industry keeps swinging between the two.

Navigation: ← 1.10.b — Component-Based CSS · 1.10.d — Real-World Folder Structure →


1. Two philosophies at a glance

Component class                         Utility classes
─────────────────────────────           ─────────────────────────────────
<button class="btn btn--primary">       <button class="bg-blue-600
  Submit                                  text-white font-bold py-2 px-4
</button>                                 rounded hover:bg-blue-700">
                                          Submit
.btn { … 12 declarations … }             </button>
.btn--primary { … 4 declarations … }
                                        Each class = 1 declaration (in CSS)

Neither is universally "right." Both solve real problems — understanding when each shines is the skill.


2. What utility classes are

A utility class maps to a single CSS declaration (sometimes two closely related ones):

ClassWhat it does
.text-centertext-align: center
.mt-4margin-top: 1rem
.flexdisplay: flex
.rounded-lgborder-radius: 0.5rem
.sr-onlyVisually hidden, accessible to screen readers

Utility libraries ship hundreds of these — Tailwind CSS is the most popular.


3. What component classes are

A component class bundles all visual rules behind one meaningful name:

.btn {
  display: inline-flex;
  align-items: center;
  padding: 0.5rem 1rem;
  font-weight: 600;
  border-radius: 0.375rem;
  cursor: pointer;
  transition: background-color 150ms;
}

Component frameworks like Bootstrap live here: you apply .btn .btn-primary and the CSS handles everything.


4. Pros and cons

CriterionUtility-firstComponent-class
Speed of prototypingVery fast — style without leaving HTMLModerate — write CSS, pick class names
ConsistencyEnforced by design tokens (spacing-4 = always 1rem)Depends on discipline
Readability of HTMLNoisy class listsClean, semantic class names
Readability of CSSMinimal custom CSS to readLarge stylesheets to navigate
File sizeSmall (purge unused)Can grow with dead selectors
RefactoringChange HTML, not CSSChange CSS, not HTML
ReusabilityExtract with @apply or framework componentsInherit / extend in CSS
Learning curveMemorise class vocabularyLearn naming conventions
Specificity issuesRare (single class, same weight)Possible if conventions break down

5. The "it's just inline styles" argument

Critics say utility classes are inline styles with extra steps. Here's why that comparison breaks down:

Inline stylesUtility classes
No media queriesResponsive variants: md:flex, lg:grid-cols-3
No pseudo-classesState variants: hover:bg-blue-700, focus:ring-2
No design constraintsConstrained scale: you can only use mt-2, mt-4, not mt-37px
Style attribute specificity (high)Class specificity (low, composable)
No reuse across elementsSame class reused everywhere
Hard to search/auditgrep "bg-blue" finds every use

Utility classes are a design-token system delivered through class names, not random inline declarations.


6. The hybrid approach

Most real projects mix both:

<!-- Component class for the card structure -->
<div class="card">
  <h2 class="card__title">Dashboard</h2>
  <!-- Utility classes for one-off spacing / alignment -->
  <p class="card__text mt-2 text-gray-600">Overview of your metrics.</p>
</div>

Rules of thumb for hybrids:

  1. Repeated patterns → extract a component class.
  2. One-off tweaks (spacing, alignment, colour overrides) → utility class.
  3. Complex interactive states → component class with modifiers.
  4. Layout primitives (flex, grid, gap) → utilities often win.

7. When utilities win vs when components win

ScenarioBetter approach
Rapid prototyping or MVPsUtilities
Design-system components used across many projectsComponent classes
Highly custom, non-repeating layoutsUtilities
Email templates (inline style fallback needed)Component classes
Large team with strict design tokensUtilities (enforced constraints)
Open-source library consumed by othersComponent classes (cleaner API)

8. Framework comparison

FrameworkPhilosophyClass example
Tailwind CSSUtility-first; extract components via @apply or framework templatesclass="flex items-center gap-4 p-4 rounded-lg shadow"
BootstrapComponent-first; utilities added later (v5+)class="btn btn-primary btn-lg"
BulmaComponent-first, no JSclass="button is-primary is-large"
TachyonsPure utility (predecessor to Tailwind's ideas)class="flex items-center pa3 br3"

9. Key takeaways

  1. Utility classes = one class, one job; composed in HTML. Fast, constrained, auditable.
  2. Component classes = semantic names; hide implementation in CSS. Clean HTML, reusable API.
  3. Utilities are not inline styles — they support responsive, pseudo-class, and design-token constraints.
  4. Most production codebases use a hybrid — components for structure, utilities for fine-tuning.
  5. The choice is not religious; match the tool to the project size, team, and reuse requirements.

Explain-It Challenge

Explain without notes:

  1. Give three concrete differences between utility classes and inline style attributes.
  2. A teammate says: "We should use only utility classes and never write component CSS." Argue for and against.
  3. When would you extract a set of utility classes into a named component class?

Navigation: ← 1.10.b — Component-Based CSS · 1.10.d — Real-World Folder Structure →