Frontend Development 15 min read

Mastering CSS Class Naming: From Chaos to BEM and Beyond

This article explores the challenges of CSS class naming, reviews the evolution from chaotic early practices through atomic and modular approaches, explains BEM conventions, and provides practical rules and code examples for creating clear, maintainable class structures in modern front‑end development.

Tencent IMWeb Frontend Team
Tencent IMWeb Frontend Team
Tencent IMWeb Frontend Team
Mastering CSS Class Naming: From Chaos to BEM and Beyond

Anyone who writes CSS has faced the dilemma of naming classes: the fear of conflicts, the desire for reusability, and the need for readability.

Typical approaches include creating a class that works, hoping it won't clash, or over‑engineering a name to avoid future issues.

Why class naming is hard

Unlike IDs, classes are meant to be reusable, but this reusability brings the risk of style collisions. Styles are applied based on specificity and source order, so a class defined in one component can be unintentionally overridden elsewhere.

The difficulty lies in balancing reuse with conflict avoidance. Simple, abstract names are easy to reuse, but they can cause clashes; more specific names reduce conflicts but increase verbosity.

<code>// BEM
.imgslide__item__img {}

// Parent scope
.imgslide .item .img {}

// Modifier
.img{}

// Special
.img--special {}

// Different pages/files
// a.html & a.css
// b.html & b.css</code>

In practice, we must solve the problem and find patterns.

Evolution of class naming

The history of class naming can be divided into four stages:

Chaos stage – no rules, arbitrary names.

Atomic stage – small, reusable utility classes.

Module stage – functional prefixes (layout, global, module).

BEM stage – structured, conflict‑free naming.

Chaos stage

Early HTML often used simple names like

h1.title

,

h2.title2

, or

div.hd

. These names are chaotic and lack clear meaning.

<code>.h1.title {}
.h2.title2 {}
.h2.title2-1 {}
.h2.title2-2 {}
.div.hd {}
.div.hd-s {}
.div.hd2 {}
.div.hd-xiangxi {}</code>

Such naming makes it hard to infer purpose and can lead to accidental style definitions.

Atomic stage

Atomic classes combine many small utilities to form a complete style:

<code>.fl{float:left;}
.fr{float:right;}
.pr{position:relative;}
.pa{position:absolute;}
.tal{text-align:left;}
.tac{text-align:center;}
.fs12{font-size:12px;}</code>

While flexible, this approach can require many classes on a single element and makes HTML‑CSS coupling tighter.

Module stage

With growing page complexity, developers introduced functional prefixes:

<code>.l-960 {}
.l-left {}
.l-right {}
.g-red {}
.g-title {}
.g-price {}
.m-login {}
.m-breadcrumb {}
.m-slide {}</code>

This reduces chaos but can become unwieldy as modules proliferate.

BEM

BEM is widely adopted in front‑end development. It ensures that a component’s styles are isolated, but class names become long and sometimes hard to remember.

Borrowing from others

Different naming stages suit different scenarios. Simple demos can use chaotic names; atomic classes work for quick utilities; modules fit layout and JS‑driven components; BEM provides a solid structure for larger projects.

Common class keywords

Layout: header, footer, container, main, content, aside, page, section

Wrapper: wrap, inner

Block: region, block, box

Structure: hd, bd, ft, top, bottom, left, right, middle, col, row, grid, span

List: list, item, field

Priority: primary, secondary, sub, minor

Size: s, m, l, xl, large, small

Status: active, current, checked, hover, fail, success, warn, error, on, off

Navigation: nav, prev, next, breadcrumb, forward, back, paging, first, last

Interaction: tips, alert, modal, pop, panel, tabs, accordion, slide, scroll, overlay

Rating: rate, star

Table: table, tr, td, cell, row

Image: img, thumbnail, original, album, gallery

Language: cn, en

Forum: forum, bbs, topic, post

Direction: up, down, left, right

Misc: btn, close, ok, cancel, switch, link, title, info, intro, more, icon, form, label, search, contact, phone, date, email, user, view, loading

Simple rules

Use hyphens to connect words, e.g.,

.item-img

.

Use double hyphens for modifiers, e.g.,

.item-img--small

.

State classes are plain words, e.g.,

.active

,

.checked

.

Prefix icon classes with

.icon-

.

Prefix JS‑controlled classes with

.js-

.

Limit combined classes to four.

Practical implementation

Start with a layout skeleton:

<code>header.header>.inner-center
section.section-feature>.inner-center
section.section-main>.inner-center
section.section-postscript>.inner-center
footer.footer>.inner-center</code>

Define base styles:

<code>.aside-block.block--xxx {
  .block-tt {}
  .block-bd {}
}
</code>

For variations, add modifier classes:

<code>.block--contact {
  .block-tt {}
}
</code>

Control scope with parent classes:

<code>.aside-block {
  .block-tt {}
  .block-bd {}
}
</code>

Apply to a contact list example:

<code>ul.contact-list {
  li {}
  .item-icon.icon-font.i-xxx {}
  .item-tt {}
  .gray {}
}
</code>

Use parent modifiers to adjust specific sections, e.g.,

.block--contact

or

.block--special

.

In summary, remember essential keywords, apply the rules for modifiers, specializations, hierarchy, and scope, and you’ll achieve clear, maintainable class naming.

Frontendbest practicesCSSBEMscssclass naming
Tencent IMWeb Frontend Team
Written by

Tencent IMWeb Frontend Team

IMWeb Frontend Community gathering frontend development enthusiasts. Follow us for refined live courses by top experts, cutting‑edge technical posts, and to sharpen your frontend skills.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.