小文一篇,说说:where、:has和:is的特殊性吧

本文探讨了CSS新推出的:where、:has和:is伪类,它们为解决逻辑化CSS提供了可能。举例说明了如何利用这些伪类在响应式页面中动态调整元素样式,尤其是:is伪类在处理第三方库样式隔离和提高CSS结构清晰性方面的优势。文章还提到了在Vue中使用:is避免scoped属性影响的问题,并提醒开发者关注这些新特性的浏览器兼容性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

css推出的:where:has:is 伪类满足了我对“逻辑化CSS”的简单幻想。

简单说下,假如你有这么一个需求:在响应式页面中,你需要判断头部元素中是否具有某一个图标,以决定 Top 文字的样式(间距、对齐方向等)。

不知道各位以前是怎么实现的。为了“性能考虑”,笔者通常是通过“动态 class”,用 js 操作元素样式。
那时候就想,如果css中就可以去判断元素就好了!但是从张鑫旭大佬那得知,我这种想法是“子元素选择”,就是父元素根据子元素调整,这样可能会带来重绘这样严重的影响。后续还要看浏览器是否会支持这种特性。

没想到,W3C推出了三种相关伪类,而浏览器也在逐渐支持。

言归正传,这三个伪类其实代表了三种特性:

  • 父元素选择 :where :简化常规选择器判断,根据父元素行为判定子元素

比如这样的问题:

.btn span > a:hover,
#header span > a:hover,
#footer span > a:hover {
}
/** 在less、sass这种预选择器中更难受!*/

变成这样的代码:

:where(.btn, #header, #footer) span > a:hover {
}
  • 子元素选择 —— :has :根据子元素行为判定父元素或其他子元素
box img { 
  aspect-ratio: 21 / 9; 
  border: 5px solid #3f51b5; 
}
 
box:has(boxing) img { 
  border: 5px solid #9c27b0; 
}
  • 双向选择 —— :is
box > :is(.boxing) {
}

或是:

box > :is(.class-a, .class-b) {
}

/** 简化自下面的代码 */
box > .class-a,
box > .class-b {
}

既然 :is:where 都有一样的特性(匹配任意一个class),那么他们有区别吗?

首先从上面的语法看是没有区别的,但是他们在优先级上有区别:我们都知道 css 选择器是有优先级的。而:where优先级是0!无论其参数重的选择器优先级有多高
:is 的优先级是由参数重的选择器优先级决定的。

这里着重说说:is 选择器吧,我发现了一个有趣的地方。
微店pc-卖家-优惠套餐设置端

这是我司商家侧一个功能,这里用了 elementui 第三方库中的 el-radio 组件。

我司脚手架是支持微前端的。在一些组件中,考虑到样式问题,我们用了 scoped 为html模板和css选择器添加随机的属性选择器,以实现css的作用域功能。(Vue特性)
图-1

那么,在如上第三方库中,我们会发现,组件内部的元素上并没有 data-v-xxx 这样的随机属性。也就是说,如果我们希望对这个元素进行样式更改,则写在 scoped 范围内就无效:

<style lang="less" scoped>
    .ce__form-limit {
        .el-radio.is-checked {
            .el-radio__label {
                color: red;
            }
        }
    }
</style>

因为这时候,Vue在编译后会给这个类名再加一个单独的属性选择器,导致无法和 DOM 中的元素匹配上!

笔者发现,在之前的这种情况中,我司之前的开发者是通过“把这个样式写在全局结构”中,比如在我们组规范的“全局样式层”文件中写入:

.el-radio.is-checked {
    .el-radio__label {
        color: red !important;
    }
}

但这种方式并不很好,笔者就曾经找这些代码找了许久… 你并没发知道后面接手的开发者是否有“耐心”看这些东西,甚至后面可能就多了许多“重复功能代码”。
ummm,包括:deep()>>> 也是一样的道理。

:is选择器拯救css结构

但是现在有了 :is !使用 is 伪类后选择器会遵循父元素的效果,而不是自己单独加一个随机属性!
(可能这和 is “子元素选择”的特性有关,为了知道子元素影响,编译时要先给它打上标记。但是 :has 伪类笔者试的是不行,这样的话这个解释就不通了,为毛同样是子供向一个可以另一个不可以?!)

还是上面的例子,我们再来看下这样的效果:

<style lang="less" scoped>
    .ce__form-limit {
        .el-radio.is-checked {
            :is(.el-radio__label) {
                color: red;
            }
        }
    }
</style>

图-2

补充一下上面的说法:
1、对React也是一样的;
2、除了第三方库组件,动态生成的DOM也不受此限制;
3、如果对兼容性有大要求的项目,可以用:-webkit-any()


期待后续更多的特性出来,各位也别闲着,一起折腾折腾“老技术”,说不定就搞出来什么名堂了呢~

不说了,才知道旧友来北京了,去拜访一下。预祝各位国庆愉快!

评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

恪愚

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值