🏗️ CSS Expert

Architecture & BEM

⏱ 1 hr3 topicsLive playground
🎯 By the end: You can name classes with the BEM convention, avoid over-specific selectors, and structure CSS so changes stay safe and predictable.

On a tiny page, any CSS works. On a real project with hundreds of rules, messy CSS becomes a nightmare: you change one thing and three others break, and nobody dares touch the file. CSS architecture is the set of habits that keep large stylesheets sane. The most popular convention is BEM, and it's refreshingly simple.

1BEM: Block, Element, Modifier

BEM is just a naming pattern for classes that makes their purpose obvious at a glance. Three parts:

  • Block — a standalone component: card, menu, button.
  • Element — a part inside a block, joined with two underscores: card__title, menu__item.
  • Modifier — a variation, joined with two dashes: card--featured, button--large.
.card { }            /* block */
.card__title { }     /* element inside the block */
.card__image { }     /* another element */
.card--featured { }  /* modifier: a special card */

Read a class like card__title--small and you instantly know: the title element, inside the card block, in its small variation. No guessing.

BEM-named components
HTML
CSS
Live preview
What's happening: Both cards share the .card block and .card__title / .card__text elements. The second one adds the .card--featured modifier for its special look — same structure, one variation. That's BEM.
Key points
  • BEM names classes as Block, Block__Element, Block--Modifier.
  • __ marks a part inside a component; -- marks a variation.
  • The class name alone tells you what an element is and where it belongs.

2Keep specificity low and flat

The deeper problem BEM solves is specificity — how strongly a selector 'wins' when rules conflict. Over-specific selectors create CSS that's impossible to override later:

/* fragile — deeply nested, hard to override */
#main .content ul li a span { color: red; }

/* sane — one flat class */
.card__link { color: red; }

Guidelines that keep a stylesheet maintainable:

  • Style with classes, not ids or long descendant chains. Classes keep specificity low and even.
  • Don't nest deeply. One flat class per thing beats four-level selectors.
  • Avoid !important — it's a sign your specificity is already out of control. Fix the selector instead.
A good test: if you can restyle any component by editing a single class without fighting other rules, your architecture is healthy.
Key points
  • Specificity decides which rule wins; over-specific selectors are impossible to override.
  • Style with flat classes, not ids or deep descendant chains.
  • Avoid !important — it signals specificity has already gone wrong.

3Which selector wins? — specificity live

When several rules set the same property on one element, the most specific one wins — regardless of the order they appear. Tick the rules below on and off and watch which colour the text takes. The four numbers show each selector's specificity as inline, id, class, element; the highest wins.

Specificity visualizer — toggle the rules
Style this text
<p id="msg" class="text">
p { color: gray }0,0,0,1WINS
.text { color: green }0,0,1,0WINS
#msg { color: orange }0,1,0,0WINS
style="color:purple" (inline)1,0,0,0WINS
Key points
  • Specificity ranking (low to high): element < class < id < inline style.
  • The most specific enabled rule wins, even if another rule comes later in the file.
  • Keeping selectors flat (single classes) keeps specificity low and predictable.

★ Practical: name a component with BEM

In any playground, build a small 'profile' component:

  1. A profile block.
  2. Elements inside it: profile__avatar, profile__name, profile__bio.
  3. A modifier profile--compact that changes its look.
  4. Style everything with single classes — no ids, no deep nesting, no !important.

Ready to test yourself?

Take the short quiz. Score 60% or more to mark this lesson complete.

Start the quiz →

💡 Log in to save your progress and earn the certificate.