由题目引发的CSS选择器优先级学习

写在前面

最近在群内,收到大佬出的一个小题目,关于CSS选择器,基于复习和学习新知识(或许不是新知识,而是自己未做了解~)的目的,遂有了以下的文章内容

题目

相关代码如下,.foo的 DOM 内容是什么颜色?

html 复制代码
  <p class="foo">Lorem ipsum</p>
css 复制代码
@layer test;
.foo.foo {
  color: red;
}

:is(.foo, #foo) {
  color: green;
}

:where(.foo, #foo) {
  color: yellow;
}

.foo {
  color: blue;
}

@layer test {
  p {
    color: purple;
  }
}

当然,我的第一反应是 red,当然是错误的~,正确答案是green

答案

我们通过浏览器的开发者工具Elements最后的styles来看下结果。

通过上图可以看出最先被干掉的是 @layer test 内的样式,然后是:where()内的样式,.foo.foo.foo的样式优先级不难理解,重复书写 class 类名选择器可以提升优先级,最后是:is()内的样式优先级最高,渲染成绿色。

通过日常的 CSS 代码书写和相关知识的阅读学习,关于元素选择器、类名选择器、属性选择器和逻辑伪类选择器相关的优先级应该是有个基础的认识。对于大佬题目中的@layer:is():where()则在日常开发中未有涉及或了解。

:where() 和 :is()

这两个选择器都是可容错选择器,接受参数均为可容错选择器列表,并且匹配规则均是任何一条规则选中的元素。 区别在于 :where():is() 匹配后的样式优先级计算规则不同,:where() 优先级总是 0,而 :is() 是由接受参数-选择器列表中的最高优先级决定,这也就不难理解 :where() 先被干掉,对于浏览器来说,他的优先级是 0,而 .foo.foo.foo 的优先级分别是10和20,自然按优先级大小依次干掉先前的,最后是 :is() 的优先级因为 .foo 匹配成功,最后优先级由列表中 #foo 决定,为 100。最后 .foo 渲染为绿色。

关于 :where():is() 的其他妙用,可以参考MDN上的一些介绍,在此,只因优先级触发的兴趣,未做其他了解,则不做赘述,感兴趣的童鞋,请自行前往~

@layer

这是个什么?大佬的博客内写了这样一句话:

@layer诞生的背景

同一个 CSS 上下文中,有些 CSS 声明需要设置低优先级,且这种优先级不受选择器权重的影响。

@layer 规则就是解决上面这种场景应运而生的。

可以让 CSS 声明的优先级下降一整个级联级别。

@layer {} 声明匿名的级联层,声明时则在{}内书写规则,之后无法为匿名级联层添加规则;

@layer layer-name {} 声明具名的级联层,同时书写规则,之后也可以继续添加规则;

@layer layer-name1, layer-name2 声明具名的级联层,不添加规则,可配置多个,先后顺序代表优先级由低到高;

@layer 可以嵌套使用,优先级比较时参考外层先比较后比较内层。

@layer 优先级

  • 级联层与不分层样式
    当级联层中设置样式时,优先级会降低,级联层外的样式会覆盖级联层中的样式,即优先级如 答案 内容所示

  • 级联层间(未声明顺序)
    按照声明的先后顺序,优先级由低到高,自上而下,与普通的样式覆盖逻辑类似,
    如题目代码改成如下:

    css 复制代码
    @layer test1 {
      .foo.foo {
        color: red;
      }
    
      :is(.foo, #foo) {
        color: green;
      }
    
      :where(.foo, #foo) {
        color: yellow;
      }
    
      .foo {
        color: blue;
      }
    }
    @layer test {
      p {
        color: purple;
      }
    }

    此时最终的渲染颜色为purple

  • 级联层间(已声明顺序)
    已声明顺序的情况下,则按照声明顺序指定优先级,先声明的优先级越低,自低至高排序
    将上述代码改动一下,在顶部添加如下代码:

    css 复制代码
    @layer test, test1;

    此时最终的渲染颜色又变成了green

选择器优先级的计算

通篇文章读到这里时,关于了解到的:where():is()的优先级计算,在上述答案解析时,已经有10100等表述,而在大佬公布完答案后,关于优先级的计算,可以通过devtools看到specificity,我们可以发现浏览器中显示的关于优先级是一个三元组(a, b, c)。关于这部分内容则通过大佬的指引,找到如下内容:

  • 在 selectors Level3 中,计算规则如下:
  • 在 selectors Level4 中,计算规则如下:

可以看出,在 selectors Level4 中,优先级的计算规则,可以理解为"按位比较"。

当然,更多的内容以及"256个class选择器可以覆盖 1 个 id选择器样式优先级 ",涉及位运算相关知识内容,可以通过源码去查看, 而对于 Due to storage limitations, implementations may have limitations on the size of A, B, or C. If so, values higher than the limit must be clamped to that limit, and not overflow. 这句话则直接表明了规范中为避免溢出,浏览器会截取掉超出的部分,如果你重复 class类名,超过 255次后,则被直接截取掉,可以自己在浏览器内进行尝试~

参考资料

相关推荐
_龙衣1 小时前
将 swagger 接口导入 apifox 查看及调试
前端·javascript·css·vue.js·css3
进取星辰2 小时前
25、Tailwind:魔法速记术——React 19 样式新思路
前端·react.js·前端框架
x-cmd3 小时前
[250512] Node.js 24 发布:ClangCL 构建,升级 V8 引擎、集成 npm 11
前端·javascript·windows·npm·node.js
夏之小星星3 小时前
el-tree结合checkbox实现数据回显
前端·javascript·vue.js
crazyme_63 小时前
前端自学入门:HTML 基础详解与学习路线指引
前端·学习·html
撸猫7913 小时前
HttpSession 的运行原理
前端·后端·cookie·httpsession
亦世凡华、4 小时前
Rollup入门与进阶:为现代Web应用构建超小的打包文件
前端·经验分享·rollup·配置项目·前端分享
Bl_a_ck4 小时前
【React】Craco 简介
开发语言·前端·react.js·typescript·前端框架
为美好的生活献上中指4 小时前
java每日精进 5.11【WebSocket】
java·javascript·css·网络·sql·websocket·网络协议
augenstern4165 小时前
webpack重构优化
前端·webpack·重构