直接用BEM类名替代嵌套选择器最有效,因浏览器从右往左匹配,4层嵌套如.header .nav .item a:hover回溯开销呈指数级增长,而.nav__item--hover单类名几乎无开销;BEM通过块(Block)、元素(Element)、修饰符(Modifier)语义化命名拍平结构,禁用标签/ID/属性选择器,严格限定嵌套仅用于媒体查询、伪类、主题切换且深度≤2。
直接用 BEM 类名替代嵌套选择器,是解决级联过深最有效、最无痛的方式。浏览器匹配 .header .nav .item a:hover 这类 4 层选择器时,性能损耗不是线性增长,而是指数级上升;而 .nav__item--hover 单类名匹配几乎无开销。
因为 CSS 解析是「从右往左」匹配的。写 .card .content p,浏览器先找所有 p,再逐个向上检查父级是否满足 .content 和 .card —— DOM 越大、层级越深,回溯路径越长。实测中,5 层嵌套在低端安卓设备上 style recalc 时间可比单类名慢 4 倍以上。
Recalculate Style 时间突然飙升,大概率就是这类选择器在拖后腿:hover、:focus 等伪类放在最右边时,会强制触发全量扫描,比 .btn--hovered 多出 2–3 倍匹配成本div p,通配行为也会污染全局匹配效率核心不是改写法,而是重构语义:把「DOM 层级关系」转译为「类名内部结构」。比如一个卡片里有标题、描述、操作按钮,不要靠 .card > .body > h3 定位,而是给每个元素分配带 block 前缀的独立类名。
product-card、user-profile,不能是泛称 card 或带位置词 top-banner
product-card__title ✅,product-card__header__logo ❌(跨层)product-card--featured ✅,product-card--bg-blue ❌(颜色应抽为 CSS 变量)完全不用嵌套不现实,但必须控制深度 ≤ 2 层,并锁定作用域。真正需要嵌套的场景其实就三类:媒体查询、伪类状态、主题切换 —— 它们都该被约束在 block 边界内。
立即学习“前端免费学习笔记(深入)”;
@media (min-width: 768px) { .navbar__item { display: flex; } },不继续写 .navbar__item .navbar__link
.button--disabled ✅,.button:disabled ❌(无法 JS 切换,破坏状态显式性):where() 降权::where(.theme-dark) .button--primary 特异性为 0,避免和 BEM 类权重打架:deep() 或 style scoped 限定穿透范围,但仅限组件内部,不跨 blockBEM 不是加几个下划线就完事,真正的难点在于 block 边界的划分 —— 一个类名该不该带 __,取决于它是不是当前 block 的**不可再分的组成部分**;一旦模糊这点,form__field-group__input 这种反模式就会悄悄出现,而工具链根本不会报错。