正确写法是.btn.primary,中间不能有空格,表示同一元素同时拥有btn和primary两个类;.btn .primary是后代选择器,会错误匹配嵌套结构。

用 .class1.class2 精准匹配多类元素,别空格
遇到一个元素同时有 btn 和 primary 两个类,写成 .btn .primary 是错的——这会匹配 .primary 在 .btn 内部的后代元素。正确写法是 .btn.primary,中间**不能有空格**。这种连写方式只匹配同时拥有这两个类的单个元素,稳定性高,且浏览器原生优化好。
常见错误现象:样式没生效、Selenium 找不到元素、document.querySelector('.a .b') 返回 null 却以为该元素存在。
- 多个类名连写时,顺序无关(
.a.b和.b.a效果一致) - 如果还要限定标签类型,加在最前,如
button.btn.primary - 避免和后代选择器混淆:带空格的是“内部找”,不带空格的是“自己必须有”
面对深度不确定的嵌套,优先用 :not() + 后代选择器排除干扰
当你要选中 .myclass 下第一个顶层 blockquote,但里面可能套着好几层 blockquote,.myclass blockquote:first-of-type 会把嵌套里的也选出来。这时候得靠 :not() 切断路径。
实际可用的选择器是:.myclass blockquote:not(blockquote blockquote)。它的意思是:“所有 .myclass 下的 blockquote,但排除那些被另一个 blockquote 直接包裹的”。这样就只留下最外层那一个。
立即学习“前端免费学习笔记(深入)”;
- 不要依赖固定层级(比如
.myclass > div > div > blockquote),结构一变就挂 -
:not()里可以写完整选择器,不限于单标签,比如:not(.nested > .item) - 注意兼容性:
:not()多层嵌套写法在 IE 不支持,现代项目基本无压力
定位“某个父容器下的最后一个直接子元素”,必须加 >
.container .some-class:last-child 很危险——它会命中所有父级下最后一个子元素中带 .some-class 的,包括嵌套里的。真正要的只是 .container 的直接子元素中的最后一个 .some-class,就得强制用直接子选择器。
正确写法:.container > .some-class:last-child。这里 > 锁定了层级关系,:last-child 才真正作用于 .container 的 immediate children。
- 如果目标不是“最后一个”,而是“第一个”,对应换成
:first-child,逻辑一样 - 若父容器下还有其他类型元素(比如
div、span混排),:last-child可能不生效,此时改用:nth-last-child(1 of .some-class)(需现代浏览器支持) - 测试时建议手动检查 DOM 结构,确认目标元素确实是父元素的 direct child
复杂结构下,别硬扛 CSS,该用 JS 就用 element.closest()
当你需要从任意嵌套层级的 .list-item.is-selected 反推它所属的顶层 .list-item(即父级是 .list、祖父级不是 .list-item 的那个),纯 CSS 几乎没法优雅表达。这时候一行 closest() 更稳。
示例:currentEl.closest('*:not(.list-item) > .list > .list-item')。这个选择器明确表达了“祖父不能是 .list-item”,closest() 自上而下匹配,天然适合这类“向上找最近符合某结构的祖先”场景。
-
closest()包含自身,所以即使当前元素就是顶层,也能返回正确结果 - 比起手写 while 循环判断 class + parentNode,代码更短、可读性更高、不易漏边界条件
- IE11 需要 polyfill,但绝大多数项目已无需兼容


















