!important是样式污染的开端,它掩盖问题而非解决,导致后续修改需更暴力覆盖;BEM通过语义化类名明确作用域与状态,提升可维护性而非单纯控制权重。

为什么!important一用就后悔
它不是“解决问题”,是把问题藏得更深——后续任何修改都得加更狠的!important,或者靠删代码来覆盖。浏览器按层叠顺序计算优先级,!important强行插队,但不改变选择器本身的权重,别人读你代码时根本看不出样式到底该由谁管。
常见错误现象:div.card span.title写好了,结果body.dark .card span.title突然生效,但你没动过.dark相关逻辑;或者组件复用时,父级传进来的style属性死活盖不过去。
- 真正该做的,是让每个样式作用域清晰、权重可预期,而不是靠暴力提升
- BEM 的
.card__title--large这类命名,天然规避了“靠嵌套深度赢”的陷阱 - 权重不再依赖
div > ul > li > a这种结构,而是靠类名唯一性锁定元素
BEM 类名怎么起才不算自欺欺人
很多人写.header__nav-item,但实际 HTML 里是包在里——这没问题;但如果.header__nav-item样式里又写了.header__nav-item:hover span,那还是回到了嵌套依赖,BEM 白写了。
使用场景:React/Vue 组件中,每个子元素都应该有独立、完整、带语义的 BEM 类名,不省略 Block 或 Element。
- 正确:
,而不是(脱离上下文就失效) - Element 名必须直接对应 DOM 节点角色,别用
__wrapper或__container这种模糊词 - Modifier 仅用于状态变更,如
button--disabled,不能用来做布局微调(那是button--full-width的事)
CSS-in-JS 或 Tailwind 下还要 BEM 吗
要,但目的变了——不是为权重,是为可维护性。Tailwind 的text-lg font-bold text-gray-800堆在一起,没人看得出这是个标题还是按钮文字;CSS-in-JS 里const title = css`font-size: 1.25rem;`,一旦多个组件共用,改一处就可能影响八方。
性能影响几乎为零,但协作成本差很多:BEM 提供的是语义锚点,比如搜索search__input--error能立刻定位到输入框报错逻辑,而不是翻遍所有input相关样式。
- Tailwind 项目中,建议用
@layer components配合 BEM 命名组织:@layer components { .search__input { @apply px-3 py-2 border; } } - CSS-in-JS 中,类名仍应保持 BEM 结构,哪怕只是作为
className的字符串值,方便搜索和重构 - 别指望工具自动帮你 BEM 化——
styled-components的asChild或attrs不会替你思考语义
嵌套选择器删不干净怎么办
老项目里.sidebar ul li a:hover这种写法,不是改个类名就能跑,得先确认它有没有被 JS 直接操作className,或者有没有用getComputedStyle读取color值。盲目替换成.nav-link--hover,可能让某个下拉菜单的高亮逻辑失效。
兼容性影响很小,但迁移节奏很重要:优先从新功能、新组件开始用 BEM,旧模块用“双类名”过渡,比如同时保留.old-list-item和加一个list-item,逐步收敛。
- 用 Chrome DevTools 的“Computed”面板,筛选
element.style和matched CSS rules,确认哪些规则真正在起作用 - 别批量替换
ul li——很多是重置默认样式,跟 BEM 无关,留着反而安全 - 最危险的是
* + *或:not(.foo) > .bar这类通用选择器,它们权重低但杀伤范围大,必须人工逐条评估
真正难的不是写对 BEM,是让团队所有人对“这个类名代表什么状态、属于哪个上下文”有共识。命名一旦松动,后面所有权重控制都会失准。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











