BEM 能系统性解决 CSS 类名冲突、样式覆盖和调试耗时问题。它通过模块化命名(如 .header__logo)、禁用嵌套选择器、语义化块名、状态修饰符(如 user-card--loading)及绑定媒体查询到单个类,确保样式隔离与可维护性。

因为不引入 BEM,复杂项目里的 CSS 类名冲突、样式覆盖、调试耗时这三件事会指数级放大——不是“可能出问题”,而是“必然失控”。
类名没上下文,改一行就炸三个页面
常见错误现象:.logo 被 reset.css 重置了宽高,header.scss 给它加了 img { width: 100% },结果弹窗里的 .logo 也变形;审查元素发现样式来源横跨 4 个文件。
根本原因:类名不回答三个问题——这个样式属于哪个模块?是哪个组件的一部分?当前是什么状态?
实操建议:
-
.header__logo和.modal__logo天然隔离,哪怕 DOM 结构完全一样也不会互相干扰 - 禁用
.header .logo这类嵌套选择器,DOM 微调(比如加个 wrapper)就不会让样式突然失效 - 所有块名必须业务语义化:
user-card✅,box❌;search-form✅,form❌
协作时没人知道谁该维护哪个类
使用场景:一个 UserCard 组件支持 loading、error、featured 三种状态,内部有头像、昵称、操作按钮。
实操建议:
- 根元素类名必须是
user-card,不能是card或profile-card - 子元素统一前缀:
user-card__avatar、user-card__name,禁止写user-card__content__name(BEM 不允许双下划线嵌套) - 修饰符通过 props 拼接:
className={`user-card${isLoading ? ' user-card--loading' : ''}`} - 这样其他开发者看到
user-card--loading就知道这是设计契约的一部分,不是临时 JS 添加的运行时状态
响应式逻辑散落各处,无法校验也无法收敛
常见错误现象:用 is-mobile 控制卡片布局,结果这个类被滥用在按钮、表单、弹窗里,最后变成全局开关;媒体查询规则分散在十几个文件中,改个断点要 grep 半小时。
实操建议:
- 整块结构变更(如网格变列表)用 Block 修饰符:
product-list--stacked - 仅元素自身微调(如图标对齐)用 Element 修饰符:
button__icon--right - 所有
@media规则必须绑定到单个 BEM 类:.product-card--mobile,禁止出现空格选择器 - 配置
stylelint-selector-bem-pattern插件,在 CI 阶段拦截.card .card__title、.btn-primary等非 BEM 写法
最常被忽略的一点:BEM 不管 CSS 加载顺序和层叠权重。如果 .card__title--large 和 .card__title--small 冲突,问题不在命名,而在构建产物里这两个类的引入顺序或特异性控制没做好——BEM 只负责让名字不歧义,不负责让样式不打架。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











