如何结合:not与:first-of-type/:first-child选择首个含a类不含b类的DOM元素
如何选择第一个带有class="a"但不带有class="b"的DOM元素?
问题背景
需要选中指定HTML结构中第一个同时拥有class="a"且不包含class="b"的<div>元素,要求使用:not结合:first-of-type或:first-child实现,避免使用当前的兄弟选择器覆盖方案。
给定HTML结构
<div class="group"> <div class="a b"></div> <div class="a b"></div> <div class="a"></div> <div class="a b"></div> <div class="a"></div> </div>
不希望使用的现有方案
.group { display: inline-flex; border: 1px solid #eee; } .group .a { width: 20px; height: 20px; background-color: #eee; border-radius: 50%; margin-left: 12px; } .group .a:first-of-type { margin-left: 0; } .group .a:not(.b) { background-color: #333; } .group .a:not(.b) ~ .a { background-color: #eee; }
解决方案
方案1:使用:has()伪类结合:first-of-type(现代浏览器支持)
利用:has()父选择器先判断.group内存在符合条件的元素,再精准选中第一个目标元素:
.group { display: inline-flex; border: 1px solid #eee; } .group .a { width: 20px; height: 20px; background-color: #eee; border-radius: 50%; margin-left: 12px; } .group .a:first-of-type { margin-left: 0; } /* 核心选择器 */ .group:has(.a:not(.b)) .a:not(.b):first-of-type { background-color: #333; }
说明::has()目前已被Chrome、Edge、Safari等现代浏览器支持,Firefox需手动开启layout.css.has-selector.enabled配置项。
方案2:纯CSS兼容方案(无需:has())
如果需要兼容不支持:has()的浏览器,可通过:not嵌套排除“前面已出现过符合条件元素”的节点,间接锁定第一个目标元素:
.group { display: inline-flex; border: 1px solid #eee; } .group .a { width: 20px; height: 20px; background-color: #eee; border-radius: 50%; margin-left: 12px; } .group .a:first-of-type { margin-left: 0; } /* 核心选择器 */ .group .a:not(.b):not(.a:not(.b) ~ .a) { background-color: #333; }
说明:这个选择器的逻辑是:先选中所有.a:not(.b)元素,再排除那些前面已经出现过.a:not(.b)的元素,最终只会保留第一个符合条件的节点。
为什么直接用.a:not(.b):first-of-type不行?
:first-of-type是基于元素类型(如<div>)匹配第一个元素,而HTML中前两个子元素都是<div class="a b">,属于同类型元素,所以.a:not(.b):first-of-type会匹配第一个<div>(即.a.b),无法选中目标元素。
内容的提问来源于stack exchange,提问作者xing huang
相关产品推荐
相关产品推荐

