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.
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--contactor
.block--special.
In summary, remember essential keywords, apply the rules for modifiers, specializations, hierarchy, and scope, and you’ll achieve clear, maintainable class naming.
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.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.