CSS Architecture and Methodologies
Structure scalable, maintainable CSS using BEM, CUBE CSS, and utility-first conventions for team-scale projects.
Overview
Key Points
- •BEM: Block__Element--Modifier keeps component styles self-contained and name-collision-free
- •Double underscore __ marks an element (child); double hyphen -- marks a modifier (variation)
- •CUBE CSS separates composition (layout), utility (single-prop), block (component), and exception (override) concerns
- •Utility-first minimizes custom CSS by composing existing single-purpose classes
- •Design tokens as CSS custom properties are the foundation any methodology builds on
- •CSS Modules and scoped CSS (in Vue/Svelte/CSS @scope) enforce automatic scoping
- •ITCSS (Inverted Triangle CSS) layers rules from generic to specific to control specificity
- •The right methodology is the one your team adopts consistently
Examples
BEM naming in practice
/* Block: the card is a self-contained component */
.card {
background: white;
border-radius: 12px;
border: 1px solid #e5e7eb;
overflow: hidden;
font-family: sans-serif;
}
/* Elements: parts that only exist inside .card */
.card__image {
width: 100%;
aspect-ratio: 16/9;
object-fit: cover;
}
.card__body {
padding: 16px;
}
.card__title {
font-size: 1.1rem;
font-weight: 700;
color: #0f172a;
margin: 0 0 8px;
}
.card__meta {
font-size: 0.8rem;
color: #6b7280;
}
/* Modifiers: variations of the block or elements */
.card--featured {
border-color: #6366f1;
box-shadow: 0 4px 20px rgba(99,102,241,0.2);
}
.card__title--large {
font-size: 1.4rem;
}BEM removes selector specificity issues. Every selector is a single class with consistent weight.
Design token system with custom properties
:root {
/* Color tokens */
--color-brand: oklch(0.55 0.2 264);
--color-text: oklch(0.15 0.02 260);
--color-muted: oklch(0.55 0.02 260);
--color-border: oklch(0.90 0.01 260);
--color-surface: oklch(0.98 0.00 0);
/* Spacing scale (powers of 1.5) */
--space-1: 4px;
--space-2: 8px;
--space-3: 12px;
--space-4: 16px;
--space-6: 24px;
--space-8: 32px;
/* Typography */
--font-body: system-ui, sans-serif;
--font-mono: ui-monospace, monospace;
--text-sm: 0.875rem;
--text-base: 1rem;
--text-lg: 1.125rem;
--text-xl: 1.25rem;
--text-2xl: 1.5rem;
--text-4xl: 2.25rem;
/* Border radius */
--radius-sm: 4px;
--radius-md: 8px;
--radius-lg: 12px;
--radius-full: 9999px;
}Design tokens as custom properties decouple the design decisions from the implementation. Changing a token updates every usage.
CUBE CSS composition layer
/* Composition layer: layout primitives with no visual styling */
/* Stack: vertical flow with consistent gap */
.stack {
display: flex;
flex-direction: column;
gap: var(--space-4, 16px);
}
/* Cluster: inline-wrap with gap */
.cluster {
display: flex;
flex-wrap: wrap;
gap: var(--space-4, 16px);
align-items: center;
}
/* Sidebar: content + aside at fixed width */
.sidebar-layout {
display: flex;
flex-wrap: wrap;
gap: var(--space-6, 24px);
}
.sidebar-layout > :first-child {
flex-basis: 240px;
flex-shrink: 0;
}
.sidebar-layout > :last-child {
flex: 1;
min-width: min(300px, 100%);
}Mixing utilities and component classes
/* Component base */
.btn {
display: inline-flex;
align-items: center;
gap: var(--space-2);
padding: var(--space-2) var(--space-4);
border-radius: var(--radius-md);
font-weight: 600;
border: 2px solid transparent;
cursor: pointer;
transition: all 0.15s ease;
font-size: var(--text-sm);
}
/* Variants as modifiers or data attributes */
.btn[data-variant="primary"] {
background: var(--color-brand);
color: white;
}
.btn[data-variant="ghost"] {
background: transparent;
color: var(--color-brand);
border-color: currentColor;
}
/* Size modifiers */
.btn[data-size="sm"] {
padding: var(--space-1) var(--space-3);
font-size: 0.8rem;
}Common Mistakes
- Deep nesting in BEM like .nav__list__item__link (more than one level of elements is a sign to split into a new block)
- Mixing methodologies inconsistently within the same project causes confusion
- Building generic utility classes without a design token foundation leads to magic numbers everywhere
- Creating a new component class for every one-off style instead of using composition or utilities
Note
Start every project with a design token layer first. Tokens give your methodology a foundation. Then add composition primitives (stack, cluster, grid). Components come last and reference the tokens.
Exercises
Write CSS to style the HTML scaffold. The preview updates live — when it looks right, mark as done.
Completed: 0 / 2 exercises
Knowledge Check
Question 1 of 3