|$ curl https://forge-ai.dev/api/markdown?path=docs/css/architecture
$cat docs/css-architecture-—-bem-/-smacss.md
updated This Week·10 min read·published

CSS Architecture — BEM / SMACSS

CSSArchitectureMethodologyIntermediate
Why CSS Architecture?

Without architecture, CSS degrades into specificity wars, unused styles, and cascading chaos. As applications grow, a methodology ensures your stylesheets remain maintainable, predictable, and scalable across teams and feature sets.

CSS architecture addresses five core problems: global namespace pollution, specificity conflicts, dead code accumulation, unclear dependencies, and inconsistent naming. Methodologies like BEM, SMACSS, ITCSS, and OOCSS each provide a different lens for solving these issues.

architecture-comparison.css
CSS
1/* Without architecture — specificity mess */
2.content .sidebar .widget .title { font-size: 18px; }
3div.widget .content > .title { font-size: 16px; }
4
5/* With BEM architecture — flat, predictable */
6.widget__title { font-size: 18px; }
7.widget__title--large { font-size: 24px; }
BEM — Block Element Modifier

BEM is the most widely adopted CSS naming convention. It stands for Block, Element, Modifier — three distinct parts of a component's structure. BEM provides a clear, strict naming convention that maps directly to component architecture.

bem-patterns.css
CSS
1.card { } /* Block — standalone component */
2.card__title { } /* Element — part of a block */
3.card__image { } /* Element — another part */
4.card__title--featured { } /* Modifier — variation of an element */
5.card--dark { } /* Modifier — variation of a block */

BEM Rules

Block: standalone entity meaningful on its own (e.g., card, header, button)
Element: semantically tied to its block (e.g., card__title, card__body)
Modifier: flag that changes appearance or behavior (e.g., card--dark, button--large)
Elements inside elements: card__title only, never card__title__icon
Double underscore separates block from element; double dash separates modifier

BEM in Practice

bem-example.css
CSS
1.card {
2 background: #1A1A2E;
3 border-radius: 8px;
4 overflow: hidden;
5}
6
7.card__image {
8 width: 100%;
9 aspect-ratio: 16 / 9;
10 object-fit: cover;
11}
12
13.card__body {
14 padding: 16px;
15}
16
17.card__title {
18 font-size: 1.25rem;
19 font-weight: 600;
20 color: #E0E0E0;
21 margin-bottom: 8px;
22}
23
24.card__text {
25 font-size: 0.875rem;
26 color: #808080;
27 line-height: 1.6;
28}
29
30.card--featured {
31 border: 2px solid #00FF41;
32}
33
34.card__title--large {
35 font-size: 1.5rem;
36}

best practice

BEM shines in component-based architectures. Each block maps to a component, elements are its DOM children, and modifiers handle variations. No nesting, no specificity wars, no guessing where styles come from.
SMACSS — Scalable Modular Architecture for CSS

SMACSS, created by Jonathan Snook, organizes CSS into five categories based on role and purpose. Unlike BEM which focuses on naming, SMACSS focuses on categorization and rules for each category type.

CategoryPrefixExamplePurpose
Baseelement selectorsbody, a, h1Default element styles, resets
Layout.l-.l-grid, .l-sidebarPage-level layout containers
Module.module-.card, .nav, .widgetReusable components
State.is-, .has-.is-active, .is-hiddenTemporary states and toggles
Theme.theme-.theme-darkVisual theming overrides
smacss-categories.css
CSS
1/* Base — reset and defaults */
2body { font-family: 'JetBrains Mono', monospace; background: #0D0D0D; color: #E0E0E0; }
3
4/* Layout — page structure */
5.l-grid { display: grid; grid-template-columns: 240px 1fr; gap: 24px; }
6.l-sidebar { width: 240px; }
7
8/* Module — components */
9.card { background: #1A1A2E; border-radius: 8px; padding: 16px; }
10
11/* State — dynamic conditions */
12.is-active { border-color: #00FF41; }
13.is-hidden { display: none; }
14
15/* Theme — visual variations */
16.theme-dark { --bg: #0D0D0D; --text: #E0E0E0; }
ITCSS — Inverted Triangle CSS

ITCSS, created by Harry Roberts, organizes stylesheets by specificity and reach — from far-reaching generic styles to narrow explicit overrides. The inverted triangle represents decreasing scope and increasing specificity as you go down.

Layer 1: Settings: variables and configuration (e.g., colors, font stacks)
Layer 2: Tools: mixins and functions
Layer 3: Generic: reset and normalize styles
Layer 4: Elements: bare HTML element styles (h1-h6, a, ul)
Layer 5: Objects: class-based layout patterns (grid, wrapper)
Layer 6: Components: specific UI components (card, button, nav)
Layer 7: Utilities: high-specificity helper classes (u-hidden, u-text-center)
itcss-layers.css
CSS
1/* Settings */
2$color-primary: #00FF41;
3$font-mono: 'JetBrains Mono', monospace;
4
5/* Tools */
6@mixin truncate { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
7
8/* Generic */
9*, *::before, *::after { box-sizing: border-box; }
10
11/* Elements */
12h1 { font-size: 2rem; color: #E0E0E0; }
13a { color: #00FF41; }
14
15/* Objects */
16.o-grid { display: grid; gap: 24px; }
17.o-wrapper { max-width: 1200px; margin: 0 auto; }
18
19/* Components */
20.c-card { background: #1A1A2E; border-radius: 8px; }
21.c-button { background: #00FF41; color: #0D0D0D; }
22
23/* Utilities */
24.u-hidden { display: none !important; }
25.u-text-center { text-align: center !important; }

info

ITCSS layers map naturally to @layers in modern CSS. You can use @layer settings, tools, generic, elements, objects, components, utilities to enforce the ordering natively.
OOCSS — Object-Oriented CSS

OOCSS, pioneered by Nicole Sullivan, treats CSS objects as reusable visual patterns. It follows two core principles: separate structure from skin, and separate container from content.

oocss-principles.css
CSS
1/* Principle 1: Separate structure from skin */
2/* Structure (one class) */
3.media { display: flex; gap: 16px; align-items: flex-start; }
4
5/* Skin (separate class) */
6.theme-dark { background: #0D0D0D; color: #E0E0E0; }
7.theme-card { background: #1A1A2E; border-radius: 8px; }
8
9/* Combined */
10<div class="media theme-card theme-dark">...</div>
11
12/* Principle 2: Separate container from content */
13/* Instead of: */
14.sidebar .media { flex-direction: column; }
15
16/* Use: */
17.media-stacked { flex-direction: column; }
18<div class="media media-stacked">...</div>
CSS Modules vs Methodologies

CSS Modules solve the same problems as methodologies but through tooling rather than naming conventions. Understanding the relationship helps you choose the right approach for your project.

AspectBEM / SMACSSCSS Modules
ScopingConvention-based namingAutomatic via build tool
Learning curveLow — just naming rulesMedium — requires build setup
OutputHuman-readable classesScoped hashed classes
DebuggingEasy — meaningful namesHarder — generated names
CombinationWorks with any approachOften paired with BEM naming
📝

note

BEM and CSS Modules are complementary, not mutually exclusive. Many teams use BEM naming inside CSS Modules for the best of both worlds: automatic scoping from the tool, and semantic naming from the convention.
Naming Conventions

Beyond BEM, several naming patterns help organize CSS and communicate intent through class names alone.

naming-conventions.css
CSS
1/* SUIT CSS — BEM variant with camelCase */
2.ComponentName { } /* PascalCase for components */
3.ComponentName-elementName { } /* camelCase for elements */
4.ComponentName-elementName--modifier { } /* modifier */
5
6/* Atomic / Functional CSS */
7.flex { display: flex; }
8.text-center { text-align: center; }
9.mt-4 { margin-top: 16px; }
10.p-2 { padding: 8px; }
11
12/* Namespace prefixes */
13.c-card { } /* Component */
14.l-grid { } /* Layout */
15.u-hidden { } /* Utility */
16.js-submit { } /* JavaScript hook (never styled directly) */
17.t-dark { } /* Theme */
Organizing Stylesheets

A well-organized stylesheet structure makes large codebases navigable. Here is a recommended file organization that combines multiple methodologies:

file-organization.css
CSS
1styles/
2├── abstracts/
3│ ├── _variables.css # colors, fonts, spacing tokens
4│ ├── _mixins.css # reusable mixins
5│ └── _functions.css # custom CSS functions
6├── base/
7│ ├── _reset.css # CSS reset / normalize
8│ ├── _typography.css # base heading, text styles
9│ └── _animations.css # @keyframes definitions
10├── layout/
11│ ├── _grid.css # grid system
12│ ├── _sidebar.css # sidebar layout
13│ └── _header.css # header layout
14├── components/
15│ ├── _card.css # card component
16│ ├── _button.css # button component
17│ └── _nav.css # navigation component
18├── pages/
19│ ├── _home.css # home-specific styles
20│ └── _dashboard.css # dashboard-specific styles
21├── themes/
22│ ├── _dark.css # dark theme overrides
23│ └── _light.css # light theme overrides
24├── vendors/
25│ └── _prism.css # third-party style overrides
26└── main.css # imports all partials in order
Choosing a Methodology

Each methodology addresses different pain points. The best choice depends on your team size, project scale, and existing tooling.

Small team, small project: BEM naming only — lightweight and effective
Large team, design system: BEM + ITCSS file structure — clear separation and predictable output
Component framework (React/Vue): CSS Modules with BEM naming — best DX with scoping
Utility-first project: Atomic/Functional CSS (Tailwind) — rapid development with constraints
Multiple themes: SMACSS categorization with theme layers — clean theming separation
Best Practices
Avoid nesting deeper than 3 levels — refactor into new components
Use specificity linters (stylelint-config-recommended) to catch issues early
Keep all states accessible: :hover, :focus, :focus-visible, :active
Document pattern libraries with Storybook or a living style guide
Audit for dead CSS regularly — consider PurgeCSS in production builds
Establish and document naming conventions in a CONTRIBUTING.md
Use CSS custom properties for tokens — they cascade naturally and support theming
Prefer class-based selectors over element or ID selectors for components
$Blueprint — Engineering Documentation·Section ID: CSS-32·Revision: 1.0