由题目引发的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 分钟前
前端 | MYTED单篇TED词汇学习功能优化
前端·学习
半开半落6 分钟前
nuxt3安装pinia报错500[vite-node] [ERR_LOAD_URL]问题解决
前端·javascript·vue.js·nuxt
理想不理想v34 分钟前
vue经典前端面试题
前端·javascript·vue.js
不收藏找不到我35 分钟前
浏览器交互事件汇总
前端·交互
YBN娜1 小时前
Vue实现登录功能
前端·javascript·vue.js
阳光开朗大男孩 = ̄ω ̄=1 小时前
CSS——选择器、PxCook软件、盒子模型
前端·javascript·css
minDuck1 小时前
ruoyi-vue集成tianai-captcha验证码
java·前端·vue.js
小政爱学习!1 小时前
封装axios、环境变量、api解耦、解决跨域、全局组件注入
开发语言·前端·javascript
魏大帅。1 小时前
Axios 的 responseType 属性详解及 Blob 与 ArrayBuffer 解析
前端·javascript·ajax