BEM前缀必须通过ESLint规则强制校验而非约定,确保类名严格匹配文件路径与组件名(如Button.tsx→.phx-button),禁止修饰符重复前缀、响应式用Modifier、状态类写入SCSS。

为什么 BEM 前缀不能只靠约定来保证
团队里有人写 .phx-button,有人写 .phoenix-button,还有人漏掉前缀直接用 .button —— 这不是命名风格问题,是构建时无法拦截的隐患。BEM 前缀一旦不统一,CSS Modules 或 scoped 的隔离能力就形同虚设,跨组件样式泄漏、调试时 class 搜索失效、主题切换逻辑错乱都会随之而来。
前缀必须绑定到具体 Block 文件路径和组件名
Phoenix 项目中所有 Block 类名都严格匹配文件路径与导出组件名:src/components/Button/Button.tsx → 根节点 class 必须为 .phx-button;src/components/SearchField/SearchField.tsx → .phx-search-field。这种绑定不是靠文档提醒,而是靠 ESLint 规则 eslint-plugin-css-modules 在构建时校验:Button.module.scss 中只允许出现以 phx-button 开头的类名,否则报错。
- 前缀长度控制在 3–4 字符(
phx-而非phoenix-),兼顾可读性与 HTML 体积 - 禁止在修饰符里重复前缀,如
.phx-button--phx-large是错的,应为.phx-button--large - Element 名不加前缀,
.phx-button__icon正确,.phx-button__phx-icon违反语义
第三方组件或 legacy CSS 怎么套进 BEM 前缀体系
直接覆盖 .el-button 或给 ant-btn 加 phx- 前缀都是徒劳,它们的样式逻辑不遵循你的 Block 边界。正确做法是用 wrapper 隔离:<div class="phx-external-button"><ElButton></ElButton></div>,然后在 phx-external-button.module.scss 中仅通过属性选择器或子选择器做有限样式透传,比如重置 margin 或对齐 vertical-align,绝不触碰 .el-button 内部结构。
前端设计与 UI/UX 全方位优化专家。覆盖视觉层次、排版系统、色彩理论、响应式布局、交互体验、动画动效、无障碍访问、性能优化八大维度,帮助开发者将普通页面升级为高品质产品级界面。前端设计与 UI/UX 全方位优化专家。覆盖视觉层次、排版系统、色彩理论、响应式布局、交互体验、动画动效、无障碍访问、性能优化八大维度,帮助开发者将普通页面升级为高品质产品级界面。
- 全局工具类(如
.clearfix)必须加命名空间:.phx-clearfix,避免污染第三方组件 - Ant Design 等库的暗色主题类(
.ant-dark)不能复用为.phx-theme--dark,二者语义不同:前者是全局环境,后者是 Block 局部状态 - 媒体查询必须收口到统一断点文件,不允许在
phx-button.module.scss里写@media (max-width: 768px)
Modifier 的前缀陷阱:别让 --size-sm 变成 --phx-size-sm
修饰符本身不承载作用域信息,它的意义完全依附于所属 Block。所以 .phx-button--large 合理,但 .phx-button--phx-large 多余且危险——它暗示这个 large 是 Phoenix 特有的,而实际只是尺寸变体。更严重的是,当多个 Block 共享同一组修饰符(如 --disabled、--loading)时,前缀重复会让枚举值失控,最终出现 .phx-button--phx-disabled 和 .phx-input--phx-disabled 两套逻辑,无法统一控制。
立即学习“前端免费学习笔记(深入)”;
- Modifier 值必须原子化、可枚举、无前缀:
--disabled、--primary、--sm - 禁止用 Modifier 表达响应式行为:
--mobile是反模式,断点应由父容器或 layout 层控制 - 状态类(如
is-loading)属于运行时 JS 控制范畴,不属于 BEM Modifier,不应出现在 SCSS 文件中
.phx-button__icon--phx-active 这种三段式嵌套。

















