CSS Architecture & Naming (BEM)
As projects grow, unstructured CSS becomes unmaintainable. CSS architecture methodologies like BEM (Block Element Modifier) provide naming conventions that keep styles organized, predictable, and scalable — even in large teams.
BEM Methodology
- Block — A standalone component: .card, .navbar, .search-form. The top-level container
- Element — A part of a block: .card__title, .card__image, .card__body. Uses double underscore
- Modifier — A variation: .card--featured, .btn--primary, .btn--large. Uses double dash
- Why BEM — Flat specificity (all single class selectors), self-documenting, avoids style conflicts
- Rules — Never style elements without their block prefix. Never nest selectors deeper than 1 level
- Common mistakes — .card__body__text is wrong. Elements don't nest. Use .card__text instead
- Alternative methodologies — SMACSS (categorized), OOCSS (object-oriented), CUBE CSS (composition + utility)
BEM in Practice
/* BEM naming convention */
/* Block */
.card { background: white; border-radius: 12px; overflow: hidden; }
/* Elements (parts of .card) */
.card__image { width: 100%; aspect-ratio: 16/9; object-fit: cover; }
.card__body { padding: 20px; }
.card__title { font-size: 1.2rem; color: #1a1a2e; margin-bottom: 8px; }
.card__description { color: #666; line-height: 1.6; }
.card__footer { padding: 12px 20px; border-top: 1px solid #eee; }
.card__tag { display: inline-block; padding: 4px 10px; background: #f0f4ff; border-radius: 12px; font-size: 0.8em; }
/* Modifiers (variations) */
.card--featured { border: 2px solid #667eea; }
.card--horizontal { display: flex; }
.card--horizontal .card__image { width: 200px; aspect-ratio: auto; }
/* Button block with modifiers */
.btn { padding: 12px 24px; border-radius: 8px; border: none; cursor: pointer; }
.btn--primary { background: #667eea; color: white; }
.btn--secondary { background: transparent; border: 2px solid #667eea; color: #667eea; }
.btn--large { padding: 16px 32px; font-size: 1.1em; }
.btn--small { padding: 8px 16px; font-size: 0.85em; }Tip
BEM keeps all selectors at single-class specificity (0,0,1,0). This means you never need !important and any style can be overridden predictably. In large teams, this predictability is more valuable than saving a few characters in class names.
BEM keeps CSS flat, readable, and avoids specificity wars
Common Mistake
.card__body__text is wrong BEM. Elements don't nest in BEM naming — use .card__text instead. The block name is always the root, and elements are flat children regardless of HTML nesting depth.
Practice Task
Refactor a component to BEM: (1) Name the block (.card), (2) Name all child elements (.card__title, .card__body, .card__footer), (3) Create modifiers (.card--featured, .card--horizontal), (4) Verify no selector has specificity higher than 0,0,1,0.
Quick Quiz
Key Takeaways
- As projects grow, unstructured CSS becomes unmaintainable.
- Block — A standalone component: .card, .navbar, .search-form. The top-level container
- Element — A part of a block: .card__title, .card__image, .card__body. Uses double underscore
- Modifier — A variation: .card--featured, .btn--primary, .btn--large. Uses double dash