CSS Methodologies (BEM, OOCSS, SMACSS)
CSS Methodologies (BEM, OOCSS, SMACSS)
Level 11 — Modern CSS Architecture & Functions Standardized naming conventions and organizational patterns (such as Block-Element-Modifier) designed to prevent class conflicts, keep specificity low, and make CSS codebases scalable and maintainable.
1. Prerequisites
- Selectors (Element, Class, ID) — Writing target classes.
- Specificity — Understanding the danger of selector matching weight.
2. Term Category
CSS Architecture (Universal Developer Standard .): CSS Methodologies (BEM, OOCSS, SMACSS) is a fundamental concept in this technology stack. Level 11 — Modern CSS Architecture & Functions
3. Explanation
(1) Design Motivation — "Why did we design this?"
When you write CSS for a simple 1-page website, you can name classes whatever you want.
But when a project grows to hundreds of pages managed by dozens of developers, writing ad-hoc CSS becomes a disaster:
- Class names collide (e.g., two developers write different
.titlerules, overriding each other). - Selector nesting gets out of control (e.g.,
.header .nav ul li .btn span a), ballooning stylesheet size and creating specificity wars. - Developers start adding
!importantto force overrides, breaking cascade logic.
To solve this scaling problem, the community created CSS Methodologies — systems of rules for how to structure and name your classes.
(2) BEM (Block, Element, Modifier)
Created by Yandex, BEM is the most widely adopted naming methodology in modern web development. It divides components into three layers:
- Block (
block): A standalone, self-contained layout component that is reusable (e.g..card,.btn,.menu). - Element (
block__element): A nested part of a block that has no standalone meaning and is tied to its parent block (uses double underscores__, e.g..card__title,.card__button). - Modifier (
block--modifierorblock__element--modifier): A flag used to change the style, state, or theme variation of a block or element (uses double hyphens--, e.g..card--featured,.btn--large,.btn--disabled).
/* BEM STYLESHEET STRUCTURE */
/* Block (Low specificity class) */
.card { background-color: white; }
/* Element (Direct style hook, flat hierarchy) */
.card__title { font-size: 1.5rem; }
/* Modifier (Variant) */
.card--featured { border: 2px solid gold; }
<!-- HTML IMPLEMENTATION -->
<div class="card card--featured">
<h2 class="card__title">Featured Item</h2>
</div>
(3) OOCSS & SMACSS
1. OOCSS (Object-Oriented CSS)
Coined by Nicole Sullivan, OOCSS focuses on separating structure (layout, width, margins) from skin (colors, gradients, themes).
- Instead of creating unique button styles, you create a generic
.btnclass for size and padding, and combine it with utility classes like.btn-primaryor.theme-darkto paint the colors.
2. SMACSS (Scalable and Modular Architecture)
Created by Jonathan Snook, SMACSS categorizes CSS rules into 5 distinct categories:
- Base: Default HTML elements reset rules (e.g.
html,body,p). - Layout: Big grid structures (e.g.
.header,.main-grid). - Module: Reusable components (corresponds to BEM Blocks).
- State: Toggles (e.g.
.is-active,.is-collapsed). - Theme: Visual skins.
(4) Code Examples
BEM Class Mapping
/* Normal, highly nested CSS (BAD - high specificity, hard to override!) */
.menu ul li a {
color: black;
}
.menu ul li a:hover {
color: red;
}
/* BEM alternative (GOOD - flat hierarchy, specificity is 10 everywhere!) */
.menu__link {
color: black;
}
.menu__link:hover {
color: red;
}
.menu__link--active {
color: blue;
}
4. Common Mistakes & Pitfalls
Mistake 1: Deep nesting BEM names (Grandchildren elements)
The mistake: Naming classes by following the exact HTML structure tree down:
/* BAD: Extremely long class names, binds styling rigidly to HTML hierarchy! */
.card__header__title__link {
color: blue;
}
Why it's wrong: BEM elements should be kept flat. You should never write grandchildren selectors. An element is always a direct child of the Block, even if it is physically nested three layers deep inside the HTML structure.
Fix: Keep names flat. Use .card__link directly, omitting the header/title levels.
Mistake 2: Violating BEM Naming Conventions by Combining Block-Element-Modifier Delimiters Incorrectly
The mistake: Writing .card_title-active or .card--title__active.
Why it's wrong: Standard BEM (Block Element Modifier) methodology uses strictly: block__element--modifier (Double Underscore __ for elements, Double Hyphen -- for modifiers).
Incorrect:
.card-title-active { } /* ❌ Ambiguous BEM naming! */
Fix:
.card__title--active { } /* Correct BEM: block__element--modifier */
Mistake 3: Over-Nesting BEM Element Selectors (.card__header__title__text)
The mistake: Writing .card__header__title__text for deeply nested elements.
Why it's wrong: BEM elements should NEVER be multi-nested (block__elem1__elem2). Keep element names flat relative to the Block root (.card__title-text).
Incorrect:
.card__header__title { } /* ❌ Multi-nested element anti-pattern! */
Fix:
.card__title { } /* Flat element name relative to Block */
5. Practice Exercises
Exercise 1: Structuring BEM Components with Block, Element, Modifier Naming
Scenario: An author structures a product card component using BEM (Block, Element, Modifier) CSS naming conventions.
Requirements:
- Define Block
.product-card. - Define Element
.product-card__title. - Define Modifier
.product-card--featured.
Answer
Implementation
/* BEM Block: Standalone entity */
.product-card {
background-color: #ffffff;
border: 1px solid #e2e8f0;
border-radius: 0.5rem;
padding: 1.5rem;
}
/* BEM Element: Child component dependent on Block (__) */
.product-card__title {
font-size: 1.25rem;
font-weight: 700;
color: #0f172a;
}
.product-card__button {
padding: 0.5rem 1rem;
background-color: #2563eb;
color: #ffffff;
}
/* BEM Modifier: Variant or state flag (--) */
.product-card--featured {
border-color: #2563eb;
box-shadow: 0 10px 15px -3px rgba(37, 99, 235, 0.1);
}
Technical Explanation
- BEM Methodology: Block, Element, Modifier naming methodology for creating modular, reusable CSS components.
- Block (
.product-card): Represents the top-level independent component container. - Element (
__title): Represents a child part inside the block, denoted by double underscores__. - Modifier (
--featured): Represents a variant or state change, denoted by double hyphens--. - Flat Specificity: Guarantees low specificity (single class name
0,1,0), eliminating CSS override wars.
Exercise 2: Preventing Specificity Bloat with BEM Naming Conventions
Scenario: Refactors deep nested CSS selectors into single-class BEM rules.
Requirements:
- Replace
.nav ul li awith.nav__link.
Answer
Implementation
/* ❌ High Specificity Nesting (Anti-Pattern):
.main-nav ul li a.active { color: blue; }
*/
/* ✅ Flat BEM Specificity (0,1,0): */
.main-nav__link--active {
color: #2563eb;
}
Technical Explanation
- Flat Specificity Architecture: BEM keeps all selectors at single-class specificity
(0,1,0). - No Cascade Lock-in: Prevents deeply nested selector chains from breaking component reusability.
- Easy Code Maintenance: Developers can update component styles without fearing unintended side effects.
Exercise 3: Comparing BEM, OOCSS, and Utility-First CSS Architectures
Scenario: Compares component-based BEM with Utility-First CSS approaches.
Requirements:
- Explain architectural trade-offs.
Answer
Implementation
/* BEM Component: Encapsulated semantic component */
.btn-primary { padding: 0.75rem 1.5rem; background: #2563eb; color: #fff; }
/* Utility-First: Single-purpose atomic utilities */
.p-4 { padding: 1rem; }
.bg-blue { background-color: #2563eb; }
Technical Explanation
- BEM Strengths: Provides clean semantic HTML markup and encapsulated component boundaries.
- Utility-First Strengths: Rapid prototyping and minimal stylesheet growth over time.
- Architectural Decision: Senior CSS Architects choose the methodology best suited for team scale.
6. Related Terms
- CSS Preprocessors (Sass & SCSS) — Tools that help organize BEM naming modules.
- CSS Reset vs. Normalize — Base architecture configs.
7. Key Takeaways
- CSS Methodologies provide standard naming conventions to keep codebases scalable.
- BEM splits components into Blocks, Elements (
__), and Modifiers (--). - BEM keeps specificity low and constant, avoiding selector overrides.
- Do not nested BEM classes into grandchildren selectors (keep elements flat).
- OOCSS separates structural layouts from aesthetic visual skins.
- SMACSS categorizes rules into Base, Layout, Module, State, and Theme buckets.