CSS Class Naming Conventions: BEM, kebab-case & CSS Modules
Content owner: · Reviewed and updated: August 9, 2026 · Review standards
For most global CSS, use lowercase kebab-case class names such as .account-summary. Add BEM structure when a component needs explicit element and modifier relationships, use camelCase when a CSS Module is accessed through JavaScript properties, and reserve is- or has- prefixes for state. The examples below show where each convention fits and where it creates unnecessary complexity.
kebab-case: The CSS Default
The CSS specification itself uses kebab-case. Every built-in property — background-color, font-family, border-top-left-radius — is hyphenated lowercase. Following the same convention for your own class names creates visual consistency with the language.
kebab-case CSS:
.user-card { ... }
.nav-bar-link { ... }
.btn-primary { ... }
--brand-color: #5b5bd6;
Pros: matches the language, URL- and HTML-friendly, easy to read. Cons: requires bracket notation if accessed from JavaScript (element.dataset['userId'] vs element.dataset.userId). For more on the snake vs kebab question, see our snake_case vs kebab-case guide.
BEM: Block, Element, Modifier
BEM is a naming methodology developed at Yandex. It uses kebab-case for words within a name, double underscores (__) to separate an element from its block, and double hyphens (--) to separate a modifier from its base. The result looks unusual at first but makes component relationships visible in the selector itself.
BEM in action:
.card — the block
.card__title — an element inside the block
.card__image — another element
.card--featured — a modifier of the block
.card__title--large — a modified element
BEM's strength is that selectors can stay flat and component relationships remain explicit. The downside is verbosity. It is useful when a team maintains traditional global CSS or SCSS, but it may add little value when CSS Modules already scope every class or when a project uses only a documented utility system.
camelCase in CSS Modules and CSS-in-JS
When CSS is imported into JavaScript via CSS Modules, styled-components, or Emotion, kebab-case names become awkward. styles.user-card is invalid JavaScript — you have to write styles['user-card']. Most CSS-in-JS ecosystems use camelCase for class names to avoid this friction.
CSS Modules + camelCase:
/* card.module.css */
.userCard { padding: 16px; }
.userCardTitle { font-weight: 700; }
// React component
import styles from './card.module.css';
<div className={styles.userCard}>...</div>
Use our Case Converter to turn kebab-case style names into JS-friendly camelCase identifiers.
Utility-First (Tailwind): Atomic Naming
Tailwind CSS replaces semantic class names with a fixed vocabulary of atomic, kebab-case utilities. Instead of writing .card-title and styling it in CSS, you compose class="text-lg font-bold mb-2" directly in the HTML. There is no naming convention to learn beyond what Tailwind provides — but you do need to enforce consistency in how you order and group classes. Plugins like Prettier's Tailwind formatter solve this automatically.
Side-by-Side Comparison
| Style | Example | Best for |
|---|---|---|
| kebab-case | .user-card | Traditional CSS, global stylesheets |
| BEM | .card__title--large | Design systems, large teams |
| camelCase | .userCard | CSS Modules, CSS-in-JS |
| Utility-first | text-lg font-bold | Component-based apps with Tailwind |
| SMACSS | .l-grid, .is-active | State and layout categorization |
Naming CSS Custom Properties
CSS custom properties (variables) are case-sensitive and require a leading double-dash: --brand-color. The convention is kebab-case, matching the rest of CSS. For design tokens, prefix them by category: --color-brand-primary, --space-md, --font-size-lg. This makes IDE autocomplete and global search dramatically more useful.
Naming Tips That Apply to Any Convention
- Be descriptive, not presentational. Use
.warning, not.red-text. The color may change; the meaning won't. - Avoid abbreviations.
.navigationbeats.nvevery time. - Singularize when an element is a single thing (
.menu), pluralize when it's a list (.menu-items). - Use a state prefix. SMACSS popularized
.is-active,.is-disabled,.has-error— they read like English and clearly mark booleans. - Pick one style and document it. The worst convention is the one half your codebase ignores.
Frequently Asked Questions
Are CSS class names case-sensitive?
Treat author-defined class values as case-sensitive in CSS selector matching. .userCard and .usercard are different class tokens, so changing capitalization can break a match.
Should I use BEM in 2026?
Use BEM when several developers share global CSS or SCSS and need visible component boundaries. Skip it when CSS Modules already provide local scope or when an established utility-only system removes the need for custom component selectors.
Can I mix kebab-case and camelCase in the same project?
Try not to. Mixing makes search-and-replace harder and increases the chance of typos. If you must mix, draw a clear line — for example, kebab-case for global utilities and camelCase only inside CSS Modules.