BEM 要求网格容器用块名(如 .dashboard),每个 grid-area 对应子元素必须带完整路径(如 .dashboard__header),内层网格应升格为独立 Block(如 .card-grid),类名描述语义而非位置,响应式仅改 grid-template-areas 不重命名。

grid-template-areas 怎么配合 BEM 写类名
不能只靠 grid-area 把布局逻辑藏在 CSS 里,否则 HTML 中的类名就失去语义锚点。BEM 要求每个可感知的区域都对应一个带块名的类,且块名必须落到实际 DOM 元素上。
常见错误是给容器加 .dashboard,然后在子元素上只写 .header、.sidebar——这些孤立类名没绑定块,等于放弃 BEM 的作用域隔离。
- 外层网格容器必须用块名:
.dashboard - 每个
grid-area对应的直接子元素,必须带完整 BEM 路径:.dashboard__header、.dashboard__sidebar、.dashboard__main-content - 禁止用
grid-column: 1 / -1强行撑满区域——这会破坏块的视觉边界,后续加边框、阴影或 padding 时容易变形
示例中 .dashboard__header 不仅声明了归属,还让搜索、复用、样式调试都可定位:搜 dashboard__ 就能拉出全部相关样式和模板片段。
BEM 下的嵌套网格区域怎么命名
内层网格(比如仪表盘里的卡片列表)不是新块的子元素,而是独立块。BEM 不允许 .dashboard__main-content__card-grid 这种三层嵌套写法。
立即学习“前端免费学习笔记(深入)”;
正确做法是把内层也视为 Block:.card-grid,它内部的元素用 .card-grid__item、.card-grid__loading 等命名。HTML 中只需在 .dashboard__main-content 下放一个 <div class="card-grid"> 即可。
<ul>
<li>每个网格区域的子内容,只要具备独立功能或复用可能,就该升格为 Block</li>
<li>
<code>.dashboard__main-content 只负责布局占位,不承担业务样式
.dashboard__main-content .card-grid ——这又引入了隐式依赖,违背 BEM “样式只属于一个块”的原则响应式重排时 BEM 类名要不要变
不需要。BEM 类名描述的是语义角色,不是视觉位置。移动端把 sidebar 挪到 main 下面,不意味着要改成 .dashboard__main-sidebar。
- 保持类名不变:
.dashboard__sidebar仍是 sidebar,只是媒体查询里改它的grid-area值 - 如果 sidebar 在移动端变成抽屉,可用修饰符:
.dashboard__sidebar--drawer,而不是重命名 - 不要用
.dashboard__sidebar-mobile这类带设备词的类名——设备不是语义,状态才是
真正该动的是 CSS 中的 grid-template-areas 字符串,比如从 "header header" "sidebar main" 改成 "header" "main" "sidebar" "footer",类名不动,结构意图依然清晰。
CSS Modules 或 Tailwind 项目里还要手写 BEM 吗
要,但目的变了:不是为了写样式,而是为了定义组件边界和可搜索锚点。
在 CSS Modules 中,button.module.css 编译后自动生成唯一哈希类名,你本不必操心命名;但保留 button、button__icon、button--primary 这些原始类名,能让团队成员快速理解组件结构、支持设计系统文档生成、方便 SSR 输出时匹配样式。
- Tailwind 项目里,
btn btn--primary不控制颜色或间距,只作为语义标记,供 JS 控制状态或工具链提取 - 邮件模板、CMS 静态页等无法运行 JS 的场景,BEM 类名是唯一可靠的样式挂载点
- 第三方组件库(如 Ant Design)需要封装 wrapper 时,
my-form__ant-date-picker比一堆:deep(.ant-picker)更稳定、更易 grep
最常被忽略的一点:BEM 类名本身不提供作用域,它只是让作用域“可读、可推断”。真要隔离,还得靠 scoped 属性、CSS Modules 或构建时编译。手写 BEM 是为了人,不是为了机器。


















