BEM在电商项目中关键在于正确使用而非是否采用,核心是准确界定Block边界、规范Element命名层级、慎用语义化Modifier、统一JS类名拼接方式,并通过工具链校验保障一致性。

直接上结论:BEM在大型电商网站里不是“要不要用”,而是“怎么避免用错”。它真正卡住团队的,从来不是命名规则本身,而是块(Block)边界的误判、修饰符(Modifier)语义的滥用,以及和现有构建链路的摩擦点。
如何定义一个合法的 Block?别把“首页轮播图”当 block
电商项目里最常踩的坑,是把带业务上下文或位置描述的词当 block 名,比如 homepage-banner、product-list-grid。这类名字一写,就锁死了复用路径——商品详情页的轮播图、搜索结果页的 banner,根本没法共用同一套样式逻辑。
- 合法 block 必须满足三个条件:独立功能、可跨页面复用、无隐含 DOM 结构依赖。例如
carousel、product-card、price-tag是合格的;top-nav不合格(“top”是位置,不是语义),应改为main-navigation - block 名必须小写 + 中划线,禁用驼峰或下划线。否则 grep 查找、Sass 变量映射、VS Code 插件自动补全全会失效
- 一个 block 对应一个 CSS 文件(如
carousel.css),且只包含以.carousel为根的选择器,不许出现.header .carousel这类上下文绑定
Element 命名为什么不能嵌套?product-card__image__caption 是错的
电商页面常见深层结构:卡片 → 图片 → 图片下方文字 → 文字里的价格标签。有人顺手写成 product-card__image__caption__price,这直接违反 BEM 语法契约,工具链(如 stylelint-selector-bem-pattern)会报错,CI 构建可能失败。
- 元素只能是一层:
product-card__image、product-card__caption、product-card__price。它们同属product-card,不存在父子层级关系 - 如果 caption 和 price 总是成对出现、样式强耦合,说明它其实该是一个新 block:
price-display,然后在 product-card 里用product-card__price-display - Sass 里禁止用嵌套写法
&__image { &__caption { ... } },这会让编译出的选择器变成非法结构
Modifier 用错比不用更危险:button--red vs button--danger
电商按钮状态多:加购、收藏、下单、禁用、加载中……但很多团队写成 button--red、button--big、button--shadow。这类修饰符无法开关,也不能预测行为,后期维护时只要换主题色,所有 --red 都得手动搜改。
立即学习“前端免费学习笔记(深入)”;
- Modifier 必须是布尔型或语义型状态:
button--primary、button--disabled、button--loading、button--outline - 视觉细节(颜色、尺寸、阴影)应由 CSS 变量或主题配置控制,而非硬编码进类名。例如
button--primary在深色主题下自动变蓝,不靠改类名 - Element 的 Modifier 必须和 Element 并列使用,不能替代 block 类:
product-card__button button--primary❌,正确是product-card__button product-card__button--primary
JS 动态拼 className 容易漏掉什么?
React/Vue 里手拼字符串 className={`product-card__button ${isDisabled ? 'product-card__button--disabled' : ''}`> 看似简单,实际极易出错:空格遗漏、大小写混用(--disabled 写成 --Disable)、漏掉基础 block 类(只写了 modifier,没写 product-card__button)。
- 必须用
clsx或封装函数,禁止字符串模板直拼。例如:clsx('product-card__button', { 'product-card__button--disabled': isDisabled }) - 不要在 JS 里写
product-card__button--disabled这种长名,提取为常量:const BUTTON_MODIFIERS = { disabled: 'product-card__button--disabled' } - 构建阶段开启
stylelint-selector-bem-pattern规则,让 CI 拦住button__icon(缺 block 前缀)或product-card__button_error(单下划线)这类低级错误
BEM 在电商项目里最难的不是写对名字,而是每次加一个 class 前,得停下来问一句:“这个样式,脱离当前页面、当前组件、当前主题,还能成立吗?” —— 答案是否定的,那它大概率不该出现在 class 名里。


















