CSS · Architecture

CSS Architecture

A 50-line stylesheet is easy. A 5,000-line one becomes chaos without a plan. CSS architecture is that plan: how you name, split and order your styles.

Advanced 5 min Lesson 23 of 26 Runnable examples
0/26 in CSS
On this page · 5 min · Advanced

Learning objectives#

  • Split CSS into base, layout, components and utilities
  • Name classes with BEM
  • Know utility-first and CSS-module approaches
  • Control cascade order with @layer

Explanation#

Layers of a stylesheet, from general to specific: reset/normalise → base (html, body, a) → layout (containers, grids) → components (card, button) → utilities (.mt-2, .text-center).

BEM naming: Block__Element--Modifier. .card is the block, .card__title an element inside it, .card--featured a variation. Every class is a single, flat selector.

Utility-first (e.g. Tailwind) uses many tiny single-purpose classes in HTML: class="p-4 rounded shadow". Fast to build, but HTML gets busy.

CSS Modules and scoped styles (React, Angular, Blazor) give each component its own class names automatically, preventing collisions.

@layer reset, base, components, utilities; declares layer order. Rules in a later layer win regardless of specificity — the end of specificity wars.

Code example: BEM components with cascade layers#

HTMLBEM components with cascade layers Runnable
<style>
  @layer reset, base, components, utilities;


  @layer reset {
    *, *::before, *::after { box-sizing: border-box; margin: 0; }
  }
  @layer base {
    body { font-family: system-ui, sans-serif; line-height: 1.5; padding: 16px; background: #f8fafc; }
  }
  @layer components {
    .card { background: white; border: 1px solid #e2e8f0; border-radius: 12px; padding: 16px; max-width: 280px; }
    .card__title { font-size: 1.1rem; margin-bottom: 4px; }
    .card__text { color: #475569; }
    .card--featured { border-color: #f59e0b; box-shadow: 0 0 0 3px #fde68a; }
  }
  @layer utilities {
    .mt-4 { margin-top: 1rem; }
    .text-center { text-align: center; }
  }
</style>


<article class="card">
  <h3 class="card__title">Basic plan</h3>
  <p class="card__text">For individuals.</p>
</article>


<article class="card card--featured mt-4 text-center">
  <h3 class="card__title">Pro plan ⭐</h3>
  <p class="card__text">For teams.</p>
</article>
Expected output
Two plan cards; the second has a highlighted amber border, extra top spacing and centred text.
Opens this example in the full playground

Step-by-step explanation#

  1. @layer declares the order once: utilities beat components, which beat base.
  2. The reset removes default margins and sets border-box.
  3. .card, .card__title and .card__text form one BEM block.
  4. .card--featured is a modifier that adds the highlight.
  5. Utilities apply small one-off tweaks and always win thanks to layer order.

Real-world use case#

Teams agree on an architecture so anyone can find a component’s styles, add a variant without breaking another page and delete CSS safely.

Common mistakes#

Deep nesting

.page .sidebar .widget ul li a creates fragile, high-specificity rules. BEM keeps every selector one class deep.

Naming by appearance

.blue-button breaks when the brand turns green. Name by role: .btn--primary.

One giant file

Split by component (button.css, card.css) and combine them in the build.

Best practices#

  • Pick one naming convention and document it
  • Keep selectors flat (one class)
  • Use @layer or a strict file order
  • Use variables for design tokens
  • Delete unused CSS regularly

Remember this#

BEM: Block__Element--Modifier → card__title, card--featured.

General → specific: reset, base, layout, components, utilities.

Later @layer wins, no matter the specificity.

Practice exercise#

Your task: Write BEM class names for a navigation bar with a list of links, where the current link is highlighted.

Need a hint?
Block = nav. Elements = list, link. Modifier = active.
Show solution
HTML Illustrative
<nav class="nav">
  <ul class="nav__list">
    <li><a class="nav__link nav__link--active" href="/">Home</a></li>
    <li><a class="nav__link" href="/about">About</a></li>
  </ul>
</nav>

Mini quiz#

CSS Architecture quizMultiple choice Question 1 of 3

In BEM, what does .card--large represent?

Score so far: 0/0

Want more? Practise all CSS MCQs · CSS interview questions

My notes#

Saved in this browser.

Progress is saved in this browser. Sign in to sync.