🚀 LEVEL UP TO SENIOR:Unlock 500+ Advanced Practical Challenges & Exercises.
🎓 COURSERA PARTNER:Earn professional Google, Meta, and IBM certificates to supercharge your resume.
CSS MASTER CLASS /// VISUAL ENGINEERING /// LAYOUT DESIGN /// ANIMATION LAB /// CSS MASTER CLASS /// VISUAL ENGINEERING ///

SMACSS: Scalable and Modular Architecture for CSS

Learn SMACSS's five-category system for organizing CSS rules, and why its State category — a dedicated is- prefix vocabulary for dynamic, JavaScript-driven UI — is worth borrowing regardless of which naming convention you otherwise use.

Total XP: 0|💻 css XP: 0

Skill Matrix

UNLOCK NODES BY LEARNING NEW TAGS.

SMACSS

Base, Layout, Module, State, Theme.


🚀 LEVEL UP TO SENIOR:Unlock 500+ Advanced Practical Challenges & Exercises.
🎓 COURSERA PARTNER:Earn professional Google, Meta, and IBM certificates to supercharge your resume.

SMACSS categorizes every rule in a stylesheet into one of five buckets: Base, Layout, Module, State, and Theme. While its Module category overlaps heavily with BEM's Block, its State category fills a gap most other methodologies leave unaddressed.

1The Five Categories At A Glance

Base styles bare HTML elements with no class (body, a, h1). Layout divides the page into major regions, using IDs for unique regions or an l- prefixed class for reusable ones (.l-sidebar). Module covers reusable, self-contained components — SMACSS's equivalent of a BEM Block. State describes how a module currently looks due to interaction or JavaScript (.is-active). Theme optionally layers on visual reskinning (color schemes, branding) separate from structural module styles.

Most projects lean heavily on Module and State day-to-day, with Base and Layout established early and touched rarely afterward — a similar pattern to how ITCSS's foundational layers stabilize quickly while Components keeps growing.

/* Base */ a { color: #00F0FF; }
/* Layout */ .l-sidebar { width: 280px; }
/* Module */ .nav-item { padding: 8px; }
/* State */ .is-active { font-weight: 700; }
localhost:3000
✓ Five Clear BucketsEvery rule in the stylesheet has an unambiguous home among Base, Layout, Module, State, or Theme.

2Why State Classes Are SMACSS's Best Idea

Most naming methodologies handle permanent visual variants well (BEM's Modifiers, for instance) but say little about *temporary, toggled* state driven by JavaScript — a menu that's open, a tab that's active, a form field that's invalid. SMACSS fills this gap directly with the is- (and sometimes has-) prefix: .is-open, .is-loading, .is-invalid.

The convention pays off in two ways. First, it's instantly greppable — searching a codebase for is- prefixed classes reliably finds every piece of dynamic, JS-toggled styling. Second, it separates *what a component structurally is* from *what state it's currently in*, letting .nav-item stay stable while .is-active gets added and removed freely by script.

.nav-item { padding: 8px 12px; }
.nav-item.is-active { border-bottom: 2px solid currentColor; }
localhost:3000
grep -r "is-" src/ →
Every JS-toggled state, found instantly

3State Classes Combine Cleanly With BEM Or CUBE CSS

You don't need to adopt SMACSS wholesale to benefit from its State category. Many BEM codebases borrow the is- prefix directly for dynamic state, using BEM naming for structure and modifiers, and SMACSS-style state classes for anything JavaScript toggles — the two conventions don't conflict because they answer different questions.

This is a useful general lesson about CSS methodologies: they're not mutually exclusive religions. ITCSS answers 'where does this rule live', BEM answers 'what do I call this class', and SMACSS's State category answers 'how do I express that this is temporary'. Mature codebases frequently combine pieces of all three.

/* BEM naming + SMACSS state, combined */
.card__toggle.is-expanded { transform: rotate(180deg); }
localhost:3000
✓ Composable MethodologiesBEM handles the component's structure; SMACSS's is- prefix handles its dynamic, toggled state — no conflict between the two.

4Step-by-Step Breakdown

Five Categories For Every Rule. SMACSS (pronounced 'smacks') sorts every rule in your stylesheet into one of five categories: Base, Layout, Module, State, and Theme. Its standout contribution is the State category — a clean, dedicated vocabulary for styling things that change dynamically, like .is-active or .is-collapsed.

Base And Layout: The Foundation. Base rules are unqualified element defaults — body, a, h1 — the styling every instance of that tag gets with no class needed. Layout rules divide the page into major regions using either ID selectors (unique regions like #header) or a l- prefixed class for reusable layout patterns (.l-grid).

Base vs Layout. In SMACSS, which category do unqualified, tag-only rules like a { color: blue; } belong to?

  • Base
  • Layout
  • Module

Module: Reusable, Independent Components. Modules are SMACSS's equivalent of BEM's Block: reusable, self-contained UI pieces like .card or .nav. Sub-parts use a single-hyphen convention (.nav-item) rather than BEM's double underscore, but the underlying intent — component-scoped, self-contained styling — is identical.

Modules As Components. What is a SMACSS Module conceptually equivalent to in BEM terminology?

  • A Block
  • An Element
  • A Modifier

State: SMACSS's Standout Contribution. State classes describe how a module currently looks due to a JavaScript-driven or interaction-driven change: .is-active, .is-collapsed, .is-disabled. The is- prefix instantly signals 'this is temporary and toggled', separating dynamic state from a module's permanent structural or cosmetic classes.

State Classes. Why does SMACSS recommend a distinct is- prefix for state classes instead of just adding another modifier?

  • Purely to keep class names shorter
  • To clearly signal the class represents temporary, JS-toggled state rather than a permanent style variant
  • Because the browser treats is- prefixed classes specially

SMACSS Categories Mapped. You now know SMACSS's five categories and, most importantly, why its State category — the is- prefix convention — is worth adopting even inside a BEM or CUBE CSS codebase, since neither of those methodologies has as clean a built-in answer for dynamic, JavaScript-driven UI state.

Write A SMACSS State Rule. SMACSS state classes like is-active describe a temporary condition, layered on top of the base styles.

Level Up 🚀

Advanced cheat sheets, SEO tricks, and interview prep for this topic.

Browser Support

ChromeSupported

Fully supported.

FirefoxSupported

Fully supported.

SafariSupported

Fully supported.

EdgeSupported

Fully supported.

Accessibility (A11y)

1State Classes Must Stay In Sync With Their ARIA Equivalents

A `.is-expanded` class toggled by JavaScript should always be paired with the corresponding `aria-expanded="true"` attribute update — the CSS class controls visual state, but assistive technology depends on the ARIA attribute, not the class name.

2Theme-Layer Overrides Must Be Re-Audited For Contrast

When a Theme layer reskins a module's colors, it can silently violate the contrast ratios the base Module was designed to satisfy — every theme variant needs its own accessibility contrast check, not just the default.

SEO Implications

  • 1

    Clear State/Structure Separation Simplifies CSS-in-Critical-Path Decisions

    Because SMACSS state classes are additive and toggled at runtime, tooling can more easily identify that a module's base styles (not its state variants) are what's needed for initial critical-path CSS.

  • 2

    A Small, Stable Base Layer Benefits From Aggressive Caching

    Base and Layout rules change rarely once established, making them good candidates for a separately cached bundle that avoids re-download on deploys that only touch Modules.

Best Practices

Never Use State Classes As The Sole Styling Hook For A Component's Core Appearance

State classes should only ever modify an existing module — a `.is-active` class with no corresponding base `.nav-item` class breaks the separation of concerns SMACSS is built around.

Keep The Theme Layer Optional And Additive

Not every project needs a Theme layer — only introduce it when you have genuine, swappable visual reskinning requirements (like light/dark mode or white-labeling), rather than by default.

Frequent Bugs

THE BUG

A JavaScript-toggled 'active' class doesn't match what screen reader users experience.

THE FIX

The `.is-active` class was updated without also updating `aria-expanded` or `aria-selected` — keep the two in sync on every toggle.

THE BUG

A dark-mode theme variant introduces text that fails contrast checks.

THE FIX

Audit contrast ratios per theme independently; a Theme layer overriding colors can break assumptions the base Module's contrast was designed around.

Real-World Examples

A Toggleable Accordion Using SMACSS State

An accordion component where JavaScript toggles both a SMACSS state class and its matching ARIA attribute together, keeping visual and assistive-technology state in sync.

el.classList.toggle('is-expanded');
el.setAttribute('aria-expanded', String(isExpanded));

Interview Prep

?Frequently Asked Questions

Pascual Vila

Pascual Vila

Frontend Instructor // Code Syllabus

Common Pitfalls & Errors

The Error //

Using a state class as a component's only styling hook

/* Wrong */ .is-active { padding: 8px; color: blue; } /* Correct */ .nav-item { padding: 8px; } .nav-item.is-active { color: blue; }

The Solution //

Pair state classes with a base module class; state should only modify, never define, a component's core appearance.

The Error //

Toggling a visual state class without updating the matching ARIA attribute

el.classList.toggle('is-expanded'); el.setAttribute('aria-expanded', String(isExpanded));

The Solution //

Update both together whenever JavaScript toggles component state.

Lesson Glossary

[01]SMACSS

Scalable and Modular Architecture for CSS, a five-category system.

Code Preview
Base/Layout/Module/State/Theme

[02]State Class

A class describing temporary, JS-toggled UI state.

Code Preview
.is-active

[03]Layout Rule

A rule defining a major structural region of the page.

Code Preview
.l-sidebar

[04]Theme Layer

An optional layer for swappable visual reskinning.

Code Preview
Dark mode

Continue Learning