SMACSS
smacss smacss (scalable and modular architecture for css) by jonathan snook categorizes css into five types — base, layout, module,
Introduction
SMACSS (Scalable and Modular Architecture for CSS) by Jonathan Snook categorizes CSS into five types — Base, Layout, Module, State, Theme — and assigns each type different specificity and naming rules. Staff engineers use SMACSS when onboarding teams to a shared stylesheet mental model: where does a new rule live, and what specificity budget does that layer get?
SMACSS is the taxonomy that prevents "just add it to main.css" — the default failure mode of enterprise CSS.
Business problem
Business pressure: Without category discipline, enterprise CSS becomes a single flat file where layout hacks override module styles and theme experiments break production. SMACSS assigns each rule a category with explicit override rules — layout can affect modules, but modules should not redefine global layout.
- Onboarding: New hires know whether a rule belongs in layout vs module within first PR review.
- Refactor safety: State classes are few and grep-able —
.is-hidden,.is-collapsed. - Theme swaps: Theme layer isolates brand experiments from structural CSS.
Why this feature exists
Platform history: Snook documented SMACSS in 2012 when responsive redesigns exposed that page-centric CSS could not scale to component-based UIs. The book predates React but maps directly to component folders today.
- Problem solved: Ambiguous ownership of global vs local styles.
- Rejected alternative: One stylesheet per page — duplication and cache misses.
- Modern role: SMACSS categories map to ITCSS layers and design-system package structure.
Browser rendering perspective
Rendering impact: Category order in the file affects cascade resolution when specificity is equal — SMACSS recommends ordering categories so theme and state win predictably without !important.
- Cascade layers (@layer): Modern SMACSS implementations map categories to explicit layers — base, layout, components, utilities.
Internal browser workflow
Workflow: Author identifies rule type → places in correct file/layer → uses category-appropriate naming → state classes prefixed with is- or has-.
- Base: element defaults, no classes.
- Layout: major regions —
l-header,l-sidebar. - Module: reusable components —
card,nav. - State:
.is-activeon module or layout. - Theme: visual skin overrides — often token-driven.
Feature deep dive
Five categories: each with naming and specificity guidance.
/* Base — single element */body { margin: 0; font-family: system-ui; }a { color: var(--link); }/* Layout — l- prefix, low specificity */.l-main { max-width: 72rem; margin: 0 auto; }/* Module — component */.nav { display: flex; }.nav__item { }/* State — is-/has- prefix, can combine */.nav__item.is-active { font-weight: 600; }.card.is-loading { opacity: 0.6; }/* Theme — override colors */.theme-dark .nav { background: #1e293b; }
Syntax
Prefixes: Layout l- (optional), state is-/has-, module unprefixed or BEM. Theme often on html or body class.
Examples
State on module — JS toggles is-expanded, CSS handles presentation:
.accordion__panel { display: none; }.accordion__panel.is-expanded { display: block; }.accordion__trigger[aria-expanded="true"] { border-color: var(--accent); }
Real-world use
Early Bootstrap grid + components followed SMACSS-like separation. Many agency style guides from 2012–2018 documented SMACSS before ITCSS gained adoption. WordPress theme frameworks use layout/module splits.
Real production example
Pattern: Monorepo packages — packages/css-base, css-layout, css-modules, css-themes. Import order enforced in build entry.
- CI: stylelint plugin rejects layout rules in module files.
- Docs: ADR maps React component folder to SMACSS category.
Enterprise use case
Enterprise: Carbon separates reset, grid, and component SCSS partials — SMACSS category thinking even with React components.
- Atlassian: Theme classes on shell; modules stay theme-agnostic.
Accessibility considerations
A11y: State classes must mirror ARIA — is-expanded paired with aria-expanded. Do not use state classes alone for semantic state.
- Focus:
.is-focus-visibleonly if native:focus-visibleinsufficient.
Performance considerations
Performance: Theme selectors like .theme-dark .module add matching cost — prefer custom properties on root for theme switches.
SEO considerations
SEO: .is-hidden with display:none on content blocks hides from crawlers — use for chrome, not article body.
Scalability considerations
Scale: State class proliferation (is-loading-42) signals missing module modifiers — consolidate.
Common production issues
Failures: Layout classes used inside modules — .l-grid .card couples components to page grid.
Debugging guide
Debug: Identify category of winning rule — if module beats layout incorrectly, specificity or order violation.
Best practices
- Prefix state classes consistently —
is-orhas-. - Modules never define page layout width.
- Theme via tokens on
:rootwhere possible. - Document category in each SCSS partial header comment.
Anti-patterns
- Global
.activestate — collides across modules. - Theme rules that change layout dimensions.
- Base layer element selectors that modules cannot override cleanly.
Trade-offs
- Benefit: clear mental model and file organization.
- Cost: category debates on edge-case components.
- vs ITCSS: SMACSS is categorical; ITCSS adds explicit specificity pyramid.
Architecture review questions
- Where does a sticky footer rule live — layout or module?
- How do state classes interact with ARIA in our accordion?
- Are theme overrides token-based or selector-based?
Interview questions
List SMACSS categories and one rule per category.(Beginner)
Base: <code>body { margin:0 }</code>. Layout: <code>.l-main</code>. Module: <code>.card</code>. State: <code>.is-active</code>. Theme: <code>.theme-dark</code> overrides.
Follow-up: How does state differ from BEM modifier?
SMACSS vs ITCSS — when use which?(Advanced)
SMACSS categorizes rule types; ITCSS orders layers by specificity. Often combined — SMACSS categories inside ITCSS layers. ITCSS adds tools/utilities at top of cascade.
Follow-up: Map SMACSS to @layer
Hands-on exercise
Exercise: Split a monolithic CSS file into SMACSS folders. Add stylelint boundaries.
Staff engineer notes
- State classes should be few — if you have 30 is-* classes, modules lack modifiers.
Common pitfalls
- Treating every modifier as global state class.
Try it yourself
Edit the CSS panel — the preview updates live. Use DevTools Performance and Accessibility panels to validate.
Try it yourself
Summary
SMACSS provides a five-category taxonomy for organizing CSS at scale — guiding where rules live and how they override each other without specificity wars.
Key takeaways
- SMACSS categorizes CSS into base, layout, module, state, theme.
- Prefixes and specificity rules prevent global collisions.