空格是后代选择器,点号连写是同时具备多个类的选择器;:not()仅支持简单选择器;属性选择器推荐类名在前;子选择器依赖dom结构易失效,应优先用语义化类名。

多个类名连写时,空格和点号的区别
空格是后代选择器,点号连写是同时具备多个类的选择器。很多人写 .btn .primary 本意是选“既有 btn 又有 primary 的元素”,结果却匹配了 <div class="btn"><span class="primary"></span></div> 这种嵌套结构。
-
.btn.primary:必须同时包含两个类,顺序无关,class="primary btn"也匹配 -
.btn .primary:只要.primary在任意层级的.btn内部就命中,容易误伤 - 浏览器解析时,点号连写比空格快——前者只查单个元素的 class 属性,后者要遍历 DOM 树找后代
:not() 里不能嵌套复合选择器
想排除带多个类的元素,比如“除了 .card.highlight.active 以外的所有 .card”,直接写 .card:not(.card.highlight.active) 是无效的——:not() 只接受简单选择器(单个标签、类、ID、伪类),不支持点号连写或空格。
- 正确写法是用逻辑“且”转义:
.card:not(.highlight):not(.active) - 如果必须依赖多个类共存的状态,建议加一个语义化新类,比如
.card--featured,再用.card:not(.card--featured) - Chrome 105+ 开始支持
:not(:is(.highlight.active)),但 Safari 16.4 之前不兼容,线上项目慎用
属性选择器 + 类选择器组合时,顺序影响可维护性
写 [data-role="tooltip"].tooltip 和 .tooltip[data-role="tooltip"] 效果一样,但后者更符合“先定位元素、再细化条件”的阅读习惯,也方便后续加其他属性约束。
- 推荐把类选择器放前面:它通常决定基础样式,属性只是微调条件
- 避免
[type="submit"].btn:disabled这种写法——type属性在表单控件中本就隐含语义,用.btn-submit:disabled更直白 - 属性值含特殊字符(如
[data-id="item-123"])必须加引号;不加引号只支持字母数字和短横线,[data-id=item_123]会解析失败
子选择器 > 和相邻兄弟 + 混用时的 DOM 脆弱性
写 .modal > .header + .body 看似精准,但只要中间插入一个无关元素(比如埋点用的 <div class="analytics-hook"></div>),整个选择器就失效。
立即学习“前端免费学习笔记(深入)”;
- 优先用类名表达关系,而不是依赖 DOM 结构:
.modal-header和.modal-body比.modal > .header + .body更稳 - 如果真要靠结构,用
:has()更语义化(如.modal:has(>.header)),但注意它目前仅 Chromium 105+ 和 Safari 15.4+ 支持,Firefox 仍需前缀 - 所有带
>或+的选择器,在组件化开发中都建议加注释说明“此选择器强依赖当前 DOM 排列”,否则半年后自己都看不懂为什么改个 div 就崩样式










