CSS Naming Conventions: camelCase, BEM, and kebab-case Compared
CSS gives you almost total freedom in naming class names, IDs, and custom properties. That freedom is also the problem. Without a convention, large stylesheets become impossible to refactor, names collide, and styles override each other in ways no one intended. Over the years the front-end community has converged on a handful of naming methodologies — BEM, SMACSS, OOCSS, and utility-first systems like Tailwind. This guide compares the main casing styles you will encounter and helps you pick one that fits your project.
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 that has become one of the most widely used systems in serious CSS codebases. 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 conveys a huge amount of structural information.
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 every selector is a single class, eliminating specificity wars. The downside is verbosity — names get long. But for design systems and component libraries where clarity matters more than terseness, BEM remains a strong choice in 2025.
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 camelCase converter to quickly convert 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?
Yes. .userCard and .usercard are two different selectors. Browsers will not silently match across cases.
Should I use BEM in 2025?
If you write traditional CSS or SCSS for a multi-developer codebase, yes — BEM still pays off. If you've adopted Tailwind or CSS-in-JS, BEM is unnecessary.
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.