.class选择器匹配class属性中包含该单词的元素,非子串匹配;.btn-primary不匹配"btn-primary-large"或"my-btn-primary";[class*="btn"]性能差于.btn;#id权重过高且存在唯一性风险;后代选择器性能随嵌套加深而下降。

.class 选择器不是“选中 class 属性值等于某个字符串”的简单匹配,而是“匹配 class 属性中**包含该单词**的任意元素”——这是绝大多数人写错样式的第一步。
为什么 .btn-primary 不生效,但 button.btn-primary 却可以?
因为 class 属性值是空格分隔的单词列表,.btn-primary 匹配的是 class 列表中**恰好存在 btn-primary 这个独立单词**的元素,不是子串匹配。常见错误:
- 写成
<div class="btn-primary-large">—— 此时btn-primary是一个整体单词,不等于btn-primary这个词,不匹配 - 写成
<div class="btn primary">—— 两个独立单词,.btn.primary才能同时命中(中间无空格) - 误以为
.btn-primary能匹配class="my-btn-primary"—— 实际不能,-是单词一部分,不是分隔符
真正安全的写法是明确语义:<button class="btn btn--primary">,再用 .btn.btn--primary 双类组合控制。
[class*="btn"] 和 .btn 的性能与语义差异
属性选择器 [class*="btn"] 看似灵活,但它是**全属性值扫描**,浏览器必须检查每个元素的 class 字符串是否包含子串 "btn",而 .btn 是 DOM 构建时就建立的类索引查找,快一个数量级。
立即学习“前端免费学习笔记(深入)”;
- 用
[class^="btn-"]匹配 BEM 风格命名(如btn-submit)可行,但仅限你完全控制 class 命名规则 -
[class~="btn"]等价于.btn,但可读性差、兼容性略低(IE9+),没必要替代点号写法 - 想批量控制带
btn的元素?优先重构 HTML,统一加class="btn",而不是靠模糊匹配
#id 选择器为什么在现代项目里越来越少见?
不是它失效了,而是它太强:单个 #header 的权重等同于 256 个 .nav-item,一旦和组件化 CSS(比如 BEM 或 CSS Modules)混用,极易引发样式覆盖失控。
- JavaScript 操作 DOM 仍需
getElementById,但样式层应避免依赖#id—— 改用.header+ 局部作用域更可控 - SSR 或微前端场景下,id 全局唯一性难保障,重复 id 会让
#id选择器只命中第一个,且校验工具(如 axe)会报 A11y 错误 - 若真需高权重定位,用
.component-header(BEM)或[data-component="header"](属性选择器)更稳妥
后代选择器 nav a 和子选择器 nav > a 的边界在哪?
关键看 HTML 结构深度。例如:
<nav>
<a href="#">Home</a>
<div class="dropdown">
<a href="#">About</a>
</div>
</nav>
-
nav a会命中全部两个<a>(包括 dropdown 内嵌的) -
nav > a只命中第一个<a>(直接子元素) - 但如果你写
nav .dropdown a,又会命中第二个 —— 这说明“层级控制”必须和结构强绑定,别指望选择器自动理解业务语义
真正容易被忽略的是:所有后代选择器都会触发浏览器对整个子树的遍历,嵌套越深,重排重绘成本越高;生产环境建议限制在 3 层以内(如 .card .content p),更深的应拆分为独立组件类。



















