BEM 命名需以业务语义为核心:瀑布流容器应命名为 .product-grid 或 .post-feed 等表达实体的 Block,禁用 waterfall 等技术性命名;子项用正交修饰符如 --ad、--fluid 控制行为;列数响应式由 .product-grid--cols-2 等修饰符驱动,而非媒体查询散落样式。

纯 CSS 瀑布流(display: grid + grid-template-columns: repeat(auto-fill, minmax(...)))本身不依赖 BEM,但一旦你要封装成可复用、可维护的组件,BEM 块的划分就直接决定后续样式是否能解耦、状态是否可控、响应逻辑是否可测。
瀑布流容器必须是一个独立 Block,不能叫 waterfall 或 grid-container
类名要表达业务意图,而不是布局实现。比如商品列表页的瀑布流,Block 名应为 .product-grid;博客首页的,则是 .post-feed。用 waterfall 会把视觉效果写死进命名里,换种布局(比如切回 masonry JS 方案或 Grid + grid-auto-flow: dense)时,类名就失去语义。
-
.product-grid表明它承载的是“商品”这一业务实体,样式只作用于该上下文 - 禁用
.grid-layout、.masonry这类暴露技术选型的名称——它们和 HTML 结构强绑定,改用 Flex 模拟列时就得全量替换类名 - 如果项目中多个页面都用瀑布流,但数据类型不同(如用户动态、活动卡片),每个都应有独立 Block 名,而非共用一个通用块
瀑布流子项不是 product-grid__item 就完事,得预留修饰符控制渲染行为
瀑布流项高度不一,常需根据内容类型或状态调整尺寸策略(比如广告位固定高、图文卡片弹性高)。这时仅靠 .product-grid__item 不够,必须配合 Modifier 控制行为,而不是在 JS 里硬塞 style 或额外 class。
- 典型修饰符:
.product-grid__item--ad(固定高度)、.product-grid__item--fluid(参与 flex 分配)、.product-grid__item--loading(占位骨架) - 修饰符必须正交:可以同时存在
.product-grid__item--ad--loading,且不互相覆盖逻辑 - 避免写
.product-grid__item--height-300这类像素值修饰符——它把响应式计算逻辑泄露到类名里,断点变化时得批量搜索替换 - 对应 CSS 中,
--fluid只设min-width: 0; flex: 1;,不写width或height
响应式列数切换不该靠媒体查询里反复改 minmax(),而应由 Block 修饰符驱动
很多人在 @media (max-width: 768px) 里重写 .product-grid 的 grid-template-columns,结果断点一多,CSS 就散落在各处。正确做法是让修饰符成为“列数意图”的开关,媒体查询只负责触发它。
立即学习“前端免费学习笔记(深入)”;
- 定义修饰符:
.product-grid--cols-1、.product-grid--cols-2、.product-grid--cols-3 - 在 CSS 中统一写:
.product-grid--cols-1 { grid-template-columns: 1fr; },.product-grid--cols-2 { grid-template-columns: repeat(2, minmax(240px, 1fr))); } - JS 或服务端根据屏幕宽度/设备类型添加对应修饰符,CSS 保持声明式、无逻辑
- 这样测试也简单:写个单元测试,断言
.product-grid--cols-2存在时,grid-template-columns是否匹配预期值
真正难的不是写出能跑的瀑布流,而是当设计师说“移动端广告位要从单列变双列,但只对会员生效”,你能否在不碰 HTML、不加新 CSS 文件、不改 JS 渲染逻辑的前提下,仅靠加一个 .product-grid--cols-2.product-grid--member-only 就完成?这取决于 Block 划分是否守住业务边界,修饰符是否只表达意图而非实现细节。


















