SCSS/CSS如何选中首个不带指定类的同类型元素
问题根源
- 原有写法存在两处核心错误:
- 伪类语法错误:
:first-of-type是伪类,规范要求使用单冒号,原写法中出现的::first-of-type是伪元素的双冒号格式,属于无效写法(部分浏览器做了容错兼容,但不符合规范)。 - 选择器逻辑认知偏差:
:first-of-type的匹配规则是仅按HTML标签名定位同父级下同标签的首个兄弟元素,完全不区分类名、属性等自定义筛选条件。示例中所有圆形元素都是<div>标签,因此永远只有最顶部的第一个div会命中:first-of-type,如果这个div带有.banned类,:first-of-type:not(.banned)就匹配不到任何元素,自然无法生效。
- 伪类语法错误:
- 需求的实际匹配逻辑为:定位所有不带
.banned类的.circle元素中,排在最靠前的第一个,该逻辑无法直接通过:first-of-type实现。
实现方案
方案1:全兼容方案(适配所有主流浏览器,无兼容性问题)
利用通用兄弟选择器~的特性实现:先给所有符合条件(不带.banned的.circle)加上目标样式,再将符合条件的元素之后所有同规则元素的样式恢复为默认,最终剩下的就是第一个符合条件的元素。
对应SCSS代码:
body { margin-top: 2rem; text-align: center; } .circle { width: 30px; height: 30px; background-color: blue; border-radius: 100%; display: inline-block; } .banned { background-color: brown; } // 匹配第一个不带.banned类的.circle元素 .circle:not(.banned) { background-color: yellowgreen; // 后续所有不带.banned类的.circle恢复默认蓝色 ~ .circle:not(.banned) { background-color: blue; } }
方案2:现代浏览器简洁写法
2023年之后发布的主流浏览器(Chrome 110+、Firefox 113+、Safari 16.4+)支持:nth-child()的of <selector>语法,可以直接在筛选后的元素集合中定位指定位置的元素,写法更直观:
body { margin-top: 2rem; text-align: center; } .circle { width: 30px; height: 30px; background-color: blue; border-radius: 100%; display: inline-block; // 直接匹配不带.banned类的.circle集合中的第一个 &:nth-child(1 of &:not(.banned)) { background-color: yellowgreen; } } .banned { background-color: brown; }
两种写法都可以满足需求:无论前面排列多少个带.banned类的圆形,第一个不带禁用类的圆形都会显示为黄绿色,后续不带禁用类的圆形保持默认蓝色。
内容的提问来源于stack exchange,提问作者user8620575
相关产品推荐
相关产品推荐

