CSS Naming Conventions: BEM, OOCSS, SMACSS Compared
Naming CSS classes might seem trivial, but in large codebases it becomes one of the most important architectural decisions. A good naming convention prevents specificity wars, reduces naming collisions, and makes stylesheets self-documenting.
Why CSS Naming Matters
CSS has a global namespace. Every class name is available everywhere, and specificity rules determine which styles win. Without a naming convention, teams inevitably create conflicts: two developers both name their class .card, and one overwrites the other.
BEM (Block Element Modifier)
BEM is the most widely adopted CSS naming convention. It uses a structured pattern:
.block {}
.block__element {}
.block--modifier {}
/* Example */
.card {}
.card__title {}
.card__image {}
.card--featured {}
.card__title--large {}
BEM Rules
- Block: A standalone component. Named in kebab-case:
.search-form,.nav-bar. - Element: A part of a block that has no standalone meaning. Double underscore separator:
.search-form__input. - Modifier: A variant or state of a block/element. Double hyphen separator:
.search-form--dark.
BEM Benefits
- Self-documenting:
.card__title--highlightedtells you exactly what it is - Low specificity: everything is a single class selector
- No naming collisions: the block name scopes everything
- Framework-agnostic: works with any tech stack
OOCSS (Object-Oriented CSS)
OOCSS separates structure from skin and container from content:
/* Structure */
.media { display: flex; align-items: start; }
.media__body { flex: 1; }
/* Skin */
.theme-dark { background: #333; color: #fff; }
.theme-light { background: #fff; color: #333; }
OOCSS creates highly reusable utility objects but can lead to many classes on a single HTML element.
SMACSS (Scalable and Modular Architecture)
SMACSS categorizes CSS rules into five types with prefixes:
| Category | Prefix | Example |
|---|---|---|
| Base | none | html, body, h1 |
| Layout | l- | .l-sidebar |
| Module | none | .card |
| State | is- | .is-active |
| Theme | t- | .t-dark |
CSS Modules and CSS-in-JS
Modern frameworks like React offer alternatives that solve naming collisions at the tooling level:
- CSS Modules: Automatically scopes class names. You write
.title, the build tool outputs.Card_title_x7kd2. Use camelCase for class names since they become JavaScript properties. - Tailwind CSS: Uses utility classes, eliminating custom naming entirely.
- styled-components / Emotion: CSS-in-JS with auto-generated class names.
Which Should You Choose?
| Approach | Best For |
|---|---|
| BEM | Traditional CSS, multi-developer teams, CMS themes |
| CSS Modules | React/Vue/Svelte component-based projects |
| Tailwind | Rapid prototyping, utility-first workflows |
| SMACSS | Large legacy codebases needing organization |
Convert Your Class Names
CSS classes always use kebab-case. Convert from other formats with our kebab-case converter. If you need camelCase for CSS Modules, try the camelCase converter or the case converter hub.