bem 能根治类名冲突、样式覆盖和调试低效问题。它要求类名必须明确表达模块归属、组件角色和状态,禁止嵌套选择器与语义模糊命名,并通过工具链强制校验落地。

因为不引入 BEM,大型项目里的类名冲突、样式覆盖、调试耗时这三件事会指数级放大——不是“可能出问题”,而是“必然失控”。
为什么 .logo 这种类名在协作中一定会出问题
常见错误现象:.logo 被 reset.css 重置了宽高,header.scss 给它加了 .logo img { width: 100% },结果弹窗里的 .logo 也变形;审查元素发现样式来源横跨 4 个文件。
根本原因:类名不回答三个问题——这个样式属于哪个模块?是哪个组件的一部分?当前是什么状态?
PigX UI Pro 前端开发指南 - Vue 3 + TypeScript + Element Plus。当用户提到 PigX UI、PigX 前端、lgb-mgui 项目、Vue 3 企业级后台开发、Element Plus 后台开发时使用此技能。
-
.header__logo和.modal__logo天然隔离,哪怕 DOM 结构完全一样也不会互相干扰 - 禁止写
.header .logo这类嵌套选择器,DOM 微调(比如加个wrapper)就不会让样式突然失效 - 所有块名必须业务语义化:
user-card✅,box❌;search-form✅,form❌
怎么写才算合规的 BEM 类名
不是加了双下划线就叫 BEM。核心是语义隔离:一个类名必须同时表达「归属」「角色」「状态」,三者缺一不可。
-
modal-close-btn是反模式——close是行为,btn是类型,混在一起既无法继承又难以定位;正确写法是modal__close(属于modal的关闭操作区),状态用修饰符:modal__close--hidden - 元素名前必须带
__,且只能直属 block,禁止嵌套:header__logo__icon错,应为header__logo+logo__icon(此时logo自身升格为 block) - 修饰符用
--连接,只表达状态或外观变体,不描述行为:button--primary✅,button--onClick❌
光靠约定没法落地,必须靠工具链“焊死”
BEM 的约束力不来自命名习惯,而来自构建时校验和编写规范。手滑一次,整个模块的样式契约就松动。
- 用
stylelint-selector-bem-pattern插件,配置{ "componentName": "[a-z][a-zA-Z0-9]+", "styleType": "bem" },自动报错.header .logo或.btn-primary - CI 流程中跑
npx stylelint "**/*.{css,scss}",失败则阻断合并——比人工检查快 10 倍,且不漏 case - 禁止在 JS 中拼接类名字符串:
className={`card__body ${isCollapsed ? 'card__body--collapsed' : ''}`}改为用cn('card__body', { 'card__body--collapsed': isCollapsed })(配合clsx)
真正难的不是写出 block__element--modifier,而是让团队在加一个 tooltip 时,本能地新建 /components/tooltip/ 而不是往 modal.css 里塞 .modal__tooltip——这需要目录约束、CI 检查、以及最初几个模块的示范性实现。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










