全局布局类名必须语义明确、单文件定义、禁用嵌套选择器;页面级容器如页头、主区等只管流式结构,不复用、无状态变体,应使用.page-header等带业务语义的命名而非模糊的BEM式命名。

全局布局类名必须语义明确、单文件定义、禁用嵌套选择器
页面级容器(如页头、主区、侧栏)不是组件,它不复用、不带状态变体、只管流式结构。用 .page-header 比 .layout__header 更合适——前者直接对应真实 DOM 角色,搜 page-header 就能定位到唯一文件;后者中 layout 是模糊词,调试时根本找不到上下文。
这类类名必须满足三个硬约束:
- 命名带业务或页面语义(
.article-page✅,.section-2❌) - 定义在独立 CSS 文件中(如
/styles/layout/PageHeader.css),不参与组件构建链路 - 禁止写
.page-header .button这类后代选择器——哪怕结构上“合理”,也会让按钮样式意外依赖布局
组件类名必须可复用、有独立作用域、只管视觉细节
局部组件(如 user-card、search-form)是真正可复用的 UI 单元,它有自己的结构、样式、行为。BEM 类名本身不隔离样式,隔离靠的是构建阶段的物理分离:比如用 CSS Modules 编译出哈希类名,或确保 .card__title 和 .page-header__title 不会打进同一份 app.css。
关键分界线在于职责:
- 布局类只写
display、grid-template-areas、min-height等容器行为属性 - 组件类才写
color、border-radius、box-shadow等视觉细节 - 如果一个类同时写了
margin-top: 60px和background: #fff,说明它已经越界了
为什么 .card__title 和 .page-header__title 不会冲突?
它们不会冲突,但前提不是“因为 BEM 名字长”,而是因为构建策略把它们隔开了。BEM 类名只是字符串,浏览器照单全收;CSS 层叠规则照常生效——如果两个类都打进 app.css,且 .page-header__title 定义在后,它就会覆盖 .card__title 的同名属性。
真正防冲突的手段是拆包与职责收敛:
-
Card.module.css→ 编译后变成_card__title_abc123,天然隔离 -
PageHeader.css→ 保持全局,但只含布局规则,避开颜色/字体等易冲突属性 - 禁止在布局文件里写
.page-header__title { font-size: 24px; color: #333; }——这是组件该干的事
容易被忽略的物理边界:文件组织比命名更重要
很多人花时间纠结 .header__nav 还是 .nav,却忘了真正起作用的是文件路径和打包方式。只要 Header.css 和 Nav.css 是两个独立文件、不被合并进同一 bundle,哪怕都叫 .header__nav,也不会互相污染。
复杂点在于:这种隔离不是自动发生的。它依赖构建配置(如 Webpack 的 CSS 提取规则)、团队约定(谁负责维护哪个目录)、以及代码审查卡点(是否允许跨目录 import 样式)。名字写对只是第一步,文件没放对位置,BEM 就只剩个空壳。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











