css部分

一、容器查询

  1. 当前状态
    目前容器查询在主流浏览器是不可用的,可以期待一下容器查询在浏览器的实现。
    浏览配置
    目前,容器查询还没有被 Chrome 浏览器正式支持,需要手动开启容器查询功能。在 Chrome 浏览器中打开(版本102之后)
    chrome://flags/#enable-container-queries,然后找到对应配置后,将 Default 改为 Enabled。
    image.png

    设置成功需要relaunch chrome
  2. 基本概念
    容器查询使我们能够根据其父元素的大小设置元素的样式,它类似于 @media查询,不同之处在于它根据容器的大小而不是视口的大小进行判断。这一直是响应式设计的一个问题,因为我们有时候希望组件能够适应它的上下文。
  3. 使用方法
    对于容器查询,需要使用 container 属性(它是 container-type 和 container-name 的缩写)指定一个元素作为容器。container-type 可以是width、height、inline-size、block-size。inline-size 和 block-size 是逻辑属性,根据文档的写入模式,它们可能会产生不同的结果。
    详见:https://developer.mozilla.org/zh-CN/docs/Web/CSS/inline-size
    简单理解:
container-type: normal; // 默认,表示不建立容器元素
container-type: size; // 表示水平和垂直方向都建立
container-type: inline-size; // 只在水平方向建立
.main, .aside {
    container: inline-size;
}

可以使用类似于媒体查询的方式来使用@container。需要注意,两者在括号中表达规则的方式有所不同(在容器查询中应该使用 inline-size > 30em 而不是 min-width: 30em)。这是媒体查询 4 级规范的一部分。当容器宽度大于 30rem 时,就切换到 flex 布局:

@container (inline-size > 30em) {
    .card {
        display: flex;
    }
}

定义container-name

main {
  container: inline-size / name;
  /* 
  * 等价于
  * container-type: inline-size;
  * container-name: name;
  */
}

@container name (max-width: 800px) {
  span {
    color: gray;
  }
}
.container-a {
    container: aside / inline-size;
}
.container-b {
    container: banner / inline-size;
}
@container banner (max-width: 480px) {
  p {
    font-weight: bold;
  }
}

再来看一个demo https://code.juejin.cn/pen/7234394067067469884

<div class="content">
  <div class="card">
    <div class="qrcode">
      <img src="https://s2.loli.net/2022/04/04/4VuT1aKLEZ3O6Mj.jpg" />
    </div>
    <div class="box">
      <div class="title">KooFE</div>
      <div class="about">介绍前端知识技巧,了解前端最新动态,欢迎大家关注!</div>
    </div>
  </div>
</div>
.content {
  container-type: inline-size;
  resize: horizontal;
  overflow: hidden;
  background: #efefef;
}

.card {
  display: flex;
  width: 600px;
  margin: 8px;
  padding: 8px;
  border-radius: 4px;
  background: #ffffff;
}

.box {
  padding-left: 16px;
}

.title {
  line-height: 36px;
  font-weight: 800;
  font-size: 20px;
}

.content .about {
  padding-top: 8px;
  line-height: 24px;
  color: #666666;
}

@container (max-width: 800px) {
  .card {
    width: 200px;
    flex-direction: column;
  }
  .box {
    padding: 0;
  }
  .about {
    display: none;
  }
}

二.其他

1.:has() 目前还没有主流浏览器支持该属性,但可以在 Safari 技术预览版中使用它。
2.@when/@else:@when/@else 是CSS中的条件规则,类似于其他编程语言中的if/else 逻辑。它可以使编写复杂的媒体查询更加符合逻辑。这里选择使用@when而不是@if是为了避免与 Sass 产生冲突。
3.media

// 原写法
@media (max-width: 750px) {
 …
}
@media (min-width: 750px) { 
        … 
}
@media (min-width: 375px) and (max-width: 750px) { 
        … 
}
// 新写法
@media (width <= 750px) {
 …
}
@media (width >= 750px) { 
        …
}
@media (375px <= width <= 750px) { 
        …
}

三、accent-color

  1. 当前状态
    目前,accent-color 在 Chrome、Edge、Firefox 和 Safari 技术预览版中已经得到了支持。不支持该属性的的浏览器会直接使用默认颜色,并且输入是完全可用的。
    2.基本概念
    color-scheme 属性允许元素指示它可以轻松呈现的配色方案。操作系统配色方案的常见选择是“亮”和“暗”,或者是“白天模式”和“夜间模式”。当用户选择其中一种配色方案时,操作系统会对用户界面进行调整。这包括表单控件、滚动条和 CSS 系统颜色的使用值。
  2. 使用方法
    用法很简单,而且该属性是可继承的。所以可以在根级别设置它,以在任何地方应用它:
:root {
   accent-color: lime;
}

可以在单个元素上使用:

form {
    accent-color: lime;
}
input[type="checkbox"] {
    accent-color: hotpink;
}
<ul id="ul">
    <li>复选框:<input type="checkbox" checked></li>
    <li>单选框<input type="radio" checked></li>
    <li>范围选择框:<input type="range"></li>
    <li>进度条:<progress value="0.8"></li>
</ul>
换个颜色:<input type="color" id="color">
<script>
console.log(color)
color.addEventListener('input', function () {
    ul.style.accentColor = this.value;
});
</script>

https://code.juejin.cn/pen/7233283786316709948

四、颜色函数

1.当前状态
Safari 目前在浏览器支持方面处于领先地位,从版本 15 就开始支持hwb()、 lch()、lab()、color(),color-mix() 和 color-contrast() 可以通过 flag 启用。Firefox 支持 hwb(),并且还标记了对 color-mix() 和 color-contrast() 的支持。令人惊讶的是,Chrome 现在还不支持这些函数。

  1. 基本概念
    我们可能已经很熟悉 Hex、RGB 和 HSL 颜色格式。CSS Color Module Levels 4 和 5 中包括一整套新的颜色函数,使我们能够以前所未有的方式在 CSS 中指定和操作颜色。它们包括:
    hwb():色相、白度、黑度。
    lab():亮度以及决定色调的 a和b值。
    lch():亮度、色度、色调。
    color-mix():将两种颜色混合在一起。
    color-contrast():从颜色列表中,输出与第一个参数相比对比度最高的颜色。
    color():指定不同颜色空间中的颜色(例如display-p3)。
  2. 使用方法
    color-mix() 将其他两种颜色混合后输出一种颜色。我们需要指定颜色插值方法作为第一个参数:
color-mix(in lch, purple 50%, plum 50%)

五、层叠层

如果我们的页面上存在非常多的样式,譬如有我们开发页面的时候的自定义样式,也有引入的组件库样式。这时候样式将会非常混乱难以管理。
当我们想覆盖一些本身非我们书写的样式时候,往往不得不通过使用优先级权重更高的样式名,去覆盖那些样式。
同时,当样式优先级感到难以控制时,开发者习惯滥用 !important 去解决,这又循环导致了后续更混乱的样式结构。
基于让 CSS 得到更好的控制和管理的背景,CSS @layer 应运而生。

何为 CSS @layer?


简单而言,CSS @规则 中的@layer声明了一个 级联层, 同一层内的规则将级联在一起, 这给予了开发者对层叠机制的更多控制。
语法也非常简单,看这样一个例子:`

layer utilities {  /* 创建一个名为 utilities 的级联层 */ }

这样,我们就创建一个名为 utilities 的 @layer 级联层。
@layer 级联层如何使用呢?

通过 @layer 级联层管理样式优先级


@layer 级联层最大的功能,就是用于控制不同样式之间的优先级。
看下面这样一个例子,我们定义了两个 @layer 级联层 A 和 B:

<div></div>
div {  
  width: 200px; 
  height: 200px; 
} 
@layer A {  
  div { 
    background: blue; 
  } 
} 
@layer B {  
  div { 
  background: green; 
  } 
}

由于 @layer B 的顺序排在 @layer A 之后,所以 @layer B 内的所有样式优先级都会比 @layer A 高,最终 div 的颜色为 green:
image.png

当然,如果页面内的 @layer 太多,可能不太好记住所有 @layer 的顺序,因此,还有这样一种写法。
我们可以同时命名多个 @layer 层,其后再补充其中的样式规则。

<div></div>
<style>
@layer B, C, A; 
div {  
  width: 200px; 
  height: 200px; 
} 
@layer A {  
  div { 
    background: blue; 
  } 
} 
@layer B {  
  div { 
    background: green; 
  } 
} 
@layer C {  
  div { 
    background: orange; 
  } 
}
</style>

上述代码,我们首先定义了 @layer B, C, A 三个 @layer 级联层。而后再后面的 CSS 代码中补充了每个级联层的 CSS 代码,但是样式的优先级为:

A > C > B

因此,最终的 div 的颜色值为 @layer A 中定义的颜色,为 blue:

image.png

到这里,CSS @layer 的作用可以清晰的被窥见。
利用 CSS @layer,我们可以将 CSS 不同模块划入不同的 @layer 中,利用先后顺序,非常好的去控制全局的样式优先级。

@layer 级联层的三种定义引入方式


上面其实提到了两种 @layer 级联层的定义引入方式,这里再描述下,一共有 3 种引入 CSS @layer 级联层的方式。
1. 直接创建一个块级的 @layer 规则,其中包含作用于该层内部的CSS规则:

@layer utilities { 
  p { 
    padding: .5rem; 
  }
}

2. 一个级联层可以通过@import 来创建,规则存在于被引入的样式表内:

@import(utilities.css) layer(utilities);

3. 创建带命名的级联层,但不指定任何样式。样式随后可在 CSS 内任意位置添加:

@layer utilities;
@layer utilities {  
  p { 
    color: red; 
  } 
}

非 @layer 包裹层与 @layer 层内样式优先级

当然,这里还会有一种情况,没有被 @layer 包裹的样式,它的优先级和被 @layer 包裹的样式相比,又会如何呢?
看这样一个例子:

<style>
@layer A { 
  a { 
    color: red; 
  } 
} 
@layer B { 
  a { 
    color: orange; 
  } 
} 
@layer C { 
  a { 
    color: yellow;
   } 
 } 
a { 
  color: green; 
} /* 未被 @layer 包裹的样式 */
</style>

这里会有一个非常重要的结论,非 @layer 包裹的样式,拥有比 @layer 包裹样式更高的优先级,因此,上述规则的排序是:
未被 @layer 包裹的样式 > @layer C > @layer B > @layer A

匿名层与嵌套层


还有两种层级关系,分别是匿名层和嵌套层。

匿名层

允许创建一个不带名字的 @layer:

@layer {  
  p { 
    margin: 1rem; 
  }
}

这里,创建了一个匿名层。匿名层的两个重要特性:

  1. 创建后无法向其再添加规则
  2. 该层和其他命名层功能一致,优先级也遵循后定义的匿名层,比其他已定义的 @layer 层,优先级更高

看一个例子:

<div></div>
<style>
div {  
  width: 200px; 
  height: 200px; 
} 
@layer {  
  div { 
    background: pink; 
  }
} 
@layer B, C, A; 
@layer A {  
  div { 
    background: blue; 
  } 
} 
@layer B {  
  div { 
    background: green; 
  } 
} 
@layer C {  
  div { 
    background: orange; 
  } 
}
</style>

上述代码,我们首先定义了一个匿名层,指定了 div 的颜色为 pink,而后又定义了 @layer B, C, A。这里优先级顺序为:

A > C > B > 匿名层

最终的颜色为 @layer A 内的颜色值 -- blue
如果,我们将匿名层放在最后的话:

<style>
div {  
  width: 200px; 
  height: 200px; 
} 
@layer B, C, A; 
@layer A {  
  div { 
    background: blue; 
  } 
} 
@layer B {  
  div { 
    background: green; 
  } 
} 
@layer C {  
  div { 
    background: orange; 
  } 
} 
@layer {  
  div { 
    background: pink; 
  } 
}
</style>

此时,样式的优先级顺序为:
匿名层 > A > C > B
最终的颜色为匿名层内的颜色值 -- pink:

嵌套层

说完了匿名层,我们再来看看嵌套层。
顾名思义,嵌套层的意思就是在 @layer 内部,我们可以再嵌套使用 @layer 级联层。像是这样:

<style>@layer A {  @layer B{ ... } }</style>

当然,它还有另外一种语法,上述代码等价于:

<style>@layer A.B {  ... }</style>

了解了这个后,那么,看这样一个例子:

<div></div>
<style>
div {  
  width: 200px; 
  height: 200px; 
} 
@layer A {  
  div { 
    background: blue; 
  }  
  @layer B { 
    div { 
      background: red; 
    } 
  } 
}
</style>

我们在 @layer A 中嵌套一个 @layer B,同时都定义了一个 div 的样式,最终 div 的 background 到底是什么颜色呢?
最终为蓝色 background: blue,为什么呢?这个很好记忆,我们假设如果没有 @layer A 这一层包裹,其实就是上述说的 @layer 层与非 @layer 层的优先级比较,这里,非 @layer 层(我们可以理解为更高级别的一层 @layer)的优先级更高。
因此,对于单个 @layer 内的嵌套关系,样式优先级为:
@layer A > @layer A.B

多层嵌套层的优先级关系

OK,再看这样一种情况:

<style>
div {  
  width: 200px; 
  height: 200px; 
} 
@layer A {  
  div { 
    background: blue; 
  } 
  @layer B { 
    div { 
      background: red; 
    } 
  } 
} 
@layer C {  
  div { 
    background: yellow; 
  } 
  @layer D { 
    div { 
      background: green; 
    } 
  }
 }
</style>

这里存在同时存在多个嵌套 @layer 的情况。那么这种情况优先级又是如何划分呢?
这里的规则是,优先级高的 @layer,无论是否存在嵌套,优先级都整体比优先级低的 @layer(无论是否存在嵌套)高,因此,这里的优先级排序是:
@layer C > @layer C.D > @layer A > @layer A.B

!important 对 CSS @layer 的影响


再来看看 !important 对 CSS @layer 的影响。
这里可以分为几种情况,先看其中一种:

<div></div>
<style>
div {  
  width: 200px; 
  height: 200px; 
  background: black;
} 
@layer A {  
  div { 
    background: blue; 
  } 
  @layer B { 
    div { 
      background: red; 
    } 
  } 
} 
@layer C {  
  div { 
    background: yellow; 
  } 
  @layer D { 
    div { 
      background: green!important; 
    } 
  } 
}
</style>

上述代码,我们给 @layer C.D 的 <div> 添加了一个 !important 规则。
如果,不考虑 !important 规则,那么实际的 CSS 优先级为(序号越高,优先级越高):

  1. @layer A.B
  2. @layer A
  3. @layer C.D
  4. @layer C
  5. 非 layer 包裹块
    那么,<div> 的颜色应该为黑色 black。然而,这里给 @layer C.D 的 <div> 添加了一个 !important 规则。
    实际上,最终 <div> 的颜色为 green,也就是最终的优先级排序为(序号越高,优先级越高):
  6. @layer A.B
  7. @layer A
  8. @layer C
  9. 非 layer 包裹块
  10. !important 下的 @layer C.D
    也就是说,这里 !important 规则的优先级还是凌驾于非 !important 规则之上的。
    上述 DEMO 还是比较有意思的。

非 @layer 包含块 !important 与 @layer 包含块 !important

到这里,你也许会以为你懂了。好,我们再来看一个 DEMO,如果我们给非 @layer 包含块,也加上一个 !important 规则,事情就变得有趣了。

<div></div>
<style>
  div {  
    width: 200px; 
    height: 200px; 
    background: black!important; 
} 
@layer A {  
  div { 
    background: blue; 
  } 
  @layer B { 
    div { 
      background: red; 
    } 
  } 
} 
@layer C {  
  div { 
    background: yellow; 
  } 
  @layer D { 
    div { 
      background: green!important; 
    } 
  } 
}
</style>

仔细看上述代码,非 @layer 包含块,我们也加上了一个 !important 规则,按照上述我能描述的规则来看,非 @layer 包含块的优先级高于 @layer 包含块,那么正常而言,我们不难猜测,这里 background: black!important 的优先级应该要比 background: green!important 高,最终 <div> 应该展示黑色。
而实际上,这里最终 <div> 的颜色还是 green。这里就又有一个非常有意思的知识点了,!important 下样式优先级的规则与非 !important 正常状态下刚好相反。
这是一个非常重要的特性,在比较正常(非 !important)规则时,越是级联(排序较后的 @layer 规则),优先级越低;反之,在比较 !important 规则时,越是级联靠后的(排序较后的 @layer 规则),优先级越高。
这个,更进一步的话,我们需要去了解 CSS Cascading 相关的知识了。

CSS Cascade 规范


在 CSS @layer 之前,我们简单看一张图:

image.png

上图表面的是在没有 CSS @layer 之前,CSS 样式申明的优先级排序,根据 CSS Cascading 4(Current Work) 标准,定义的当前规范下申明的层叠顺序优先级如下(越往下的优先级越高,下面的规则按升序排列):

  • Normal user agent declarations
  • Normal user declarations
  • Normal author declarations
  • Animation declarations
  • Important author declarations
  • Important user declarations
  • Important user agent declarations
  • Transition declarations

    按照上述算法,可以得到一个样式优先级的排序,大概是这样(越往下的优先级越高,下面的规则按升序排列):
    image.png
  1. User Agent - 用户代理普通样式
  2. User - 用户设置的普通样式
  3. Author - 页面作者普通样式
  4. Animations - 动画样式
  5. ❗️Author - 页面作者 !important 样式
  6. ❗️User - 用户设置的 !important 样式
  7. ❗️User Agent - 用户代理的 !important 样式
  8. Transitions - 过渡样式

简单解释一下:
用户代理样式:浏览器会有一个基本的样式表来给任何网页设置默认样式。这些样式统称用户代理样式
页面作者样式:网页的作者可以定义文档的样式,这是最常见的样式表。大多数情况下此类型样式表会定义多个,它们构成网站的视觉和体验,即页面主题,可以理解为页面作者样式
用户样式:读者,作为浏览器的用户,可以使用自定义样式表定制使用体验,自定义用户偏好,可以理解为用户样式

关于 CSS Cascading,也就是层叠规范,你可以看看我的这篇文章加深理解 -- 深入理解 CSS(Cascading Style Sheets)中的层叠(Cascading)

而当有了 CSS @layer 之后,这个层叠优先级顺序有了更新,具体优先级如下:
image.png

整体会变更为复杂一些,但是总体还是遵循了两个规则:

  1. !important 样式高于非 !important 样式
  2. 在比较 !important 规则时,优先级顺序与正常规则相反,在正常状态下优先级越低的,在 !important 下优先级越高

总结一下

综上,便是关于 CSS @layer 的基础相关知识。
CSS @layer 的诞生,让我们有能力更好的划分页面的样式层级,更好的处理内部样式与外部引用样式的优先级顺序,属于比较重大的一次革新。

同时,它也让我们意识到要逐渐摒弃大规模使用 !important 去覆盖样式优先级的错误做法,避免许多因为优先级问题带来的不必要的副作用。来看一眼兼容性:
image.png
虽然红了一大片,但是,在最新版的 Chrome、Safari、Firefox、Edge 都已经开始支持 CSS @layer,并且,目前已经可以通过一些 polyfill 初步使用它,相信在不久的将来,它将会成为业务 CSS 代码中必不可少的一部分。

六、aspect-ratio 为元素设置宽高比

.img_container {
  width: 100%;
  aspect-ratio: 16 / 9;
}

用于防止图片加载后对页面布局的影响,亦可用于媒体查询

七、新的 CSS 伪类函数 :is() 和 :where()

:where() 函数接受一个选择器列表作为参数,允许你编写更少的代码并同时设置它们的样式。下面,我们将讨论 :where() 伪类函数,并演示如何在生产环境中使用它。我们将回顾与 :where() 函数相关的叠加、优先级和安全性。我们还将研究一些特定的用例,并讨论它与 :is() 函数的异同。

1.什么是 :where() 函数?

根据 MDN,:where() 是一个 CSS 伪类函数选择器,它接受一个选择器列表作为参数,并将给定的样式应用于该列表中的任何元素,因此:where() 对于缩短一个较长的选择器列表非常有用。
在 CSS 中,当多个元素同时应用相同的样式规则时,我们通常会编写一长串以逗号分隔的选择器。
下面是一个例子,我们将相同的样式应用到 header、main 元素和 footer 元素中的所有 <a> 标签:

header a:hover,
main a:hover,
footer a:hover {
  color: green;
  text-decoration: underline;
}

在上面的代码片段中,我们只选择了三个元素,但是如果有大量的元素和选择器,代码将开始看起来不整洁,并且可能变得难以阅读和理解。这就是 :where() 伪类函数发挥作用的地方。
下面是上面的例子使用 :where() 函数的样子:

:where(header, main, footer) a:hover {
  color: red;
  text-decoration: underline;
}

当浏览器到达该代码片段时,该代码指示浏览器查找 header、main 和 footer 选择器,并定位这些选择器中的所有 a 标签。然后,当用户将鼠标悬停在任何这些 a 标签上时,浏览器应该应用指定的样式,在本例中为绿色和下划线。这个伪类函数使我们能够以更短、更容易理解的方式编写一个很长的选择器列表。

2. 组合、分割和叠加 :where() 函数

使用 :where() 函数,我们可以以多种方式和组合对元素进行分组。我们可以将 :where() 函数放在选择器的开头、中间或结尾。下面是一个有多个选择器和样式的例子:

/* first list */
header a:hover,
main a:hover,
footer a:hover {
  color: green;
  text-decoration: underline;
}
/* second list */
article header > p,
article footer > p{
    color: gray;
}
/* third list */
.dark-theme button,
.dark-theme a,
.dim-theme button,
.dim-theme a{
    color: purple;
}

下面是相同的代码,用 :where() 函数重写:

/* first list */
/* at the beginning */
:where(header, main, footer) a:hover {
  color: red;
  text-decoration: underline;
}
/* second list */
/* in the middle */
article :where(header, footer) > p {
    color: gray;
}
/* third list */
/* at the end */
.dark-theme :where(button, a) {
    color: purple;
}
.dim-theme :where(button, a) {
    color: purple;
}

在第一个列表中,我们指定红色和下划线样式应应用于悬停时的 header、main 元素和 footer 元素。在第二个列表中,我们指定 article、header 和 footer 元素应该使用灰色样式。
为了更清晰,我们将第三个列表分为两个 :where() 函数。在这个列表中,我们指定 .dark-theme、.dim-theme 里的 button 和 a 元素的样式应该是紫色。
现在,我们将进一步减少第三个列表函数,将它们变成一个 :where() 函数:

/* stacked */
:where(.dark-theme, .dim-theme) :where(button, a) {
  color: purple;
}

这种减少复杂选择器列表的策略称为叠加。

3. :where() 选择器的优先级

:where() 函数选择器的优先级总是零。因此,以该函数为目标的任何元素也会自动获得 0 的优先级。这使我们能够轻松地取消任何元素的样式。
下面是一个 HTML 有序列表的例子:

<div>
  <h2>First list no class</h2>
  <ol>
    <li>List Item 1</li>
    <li>List Item 2</li>
  </ol>
</div>
<div>
  <h2>Second list with class</h2>
  <ol class="second-list">
    <li>List Item 1</li>
    <li>List Item 2</li>
  </ol>
</div>

<div>
  <h2>Third list with class</h2>
  <ol class="third-list">
    <li>List Item 1</li>
    <li>List Item 2</li>
  </ol>
</div>

在上面的代码片段中,有三个有序列表,每个列表中有两个项。第二个和第三个列表有一个给定的类,而第一个列表没有。

没有任何样式,我们可以看到每个列表是按数字顺序排列的:
image.png

现在,让我们添加一些样式:
:where(ol[class]) {
    list-style-type: none;
}

在上面的代码片段中,我们使用 :where() 伪类函数来选择应用了类的所有 ol 标签。

下面,我们看到第二个和第三个列表,它们都有一个类,被 :where() 函数作为目标,并删除了它们的 list-style-type:
image.png
现在,让我们添加一些额外的样式:
:where(ol[class]) {
  list-style-type: none;
}
.second-list {
  list-style-type: disc;
}
image.png

你可能会想,“这不应该是这样吗,因为新的样式写在 :where() 函数样式下面?”不,它不是,我们一会儿就会看到。
让我们看看当我们把刚刚添加的代码移到代码块的顶部,并把 :where() 函数部分移到底部时,会发生什么:

.second-list {
  list-style-type: disc;
}
:where(ol[class]) {
  list-style-type: none;
}

注意样式仍然没有改变
记住,:where() 函数的优先级为零。

4. :where() 选择器的安全性

对于选择器列表,如果浏览器不能识别列表中的一个选择器,则整个选择器列表将被视为无效,并且它们的样式将不会被应用。然而,对于 :where() 伪类函数就不是这样了。
如果 :where() 函数中的元素是无效选择器的目标,则该元素将不会获得任何样式。其余的元素仍然会被设置样式。:where() 函数将跳过无效的选择器到下一个(有效)选择器。这就是为什么 :where() 被称为安全的选择器。
在下面的例子中,:unsupported 对于许多浏览器来说是无效的选择器。下面的代码将被正确解析,并且仍然会匹配 :valid 选择器,即使在不支持 :unsupported 选择器的浏览器中,如下所示:

:where(:valid, :unsupported) {
  `...
}

然而,在不支持 :unsupported 选择器的浏览器中,以下代码将被忽略,即使它们支持 :valid 选择器:

:valid, :unsupported {
  ...
}

5. :where() 函数的特殊用例

在一些特殊的用例中,:where() 函数可能是一个有用的工具,但也有一些情况下应该避免使用它。使用 :where() 伪类函数时出现的几乎所有问题都归结为优先级。因为 :where() 的优先级为零,我们需要非常小心地选择何时何地使用这个函数。
首先,让我们看看几个用例,在这些用例中 :where() 可能特别有用。

5.1 改进 CSS 重置
CSS 重置是指在任何其他样式之前加载一组样式规则,以清除浏览器的内置样式。CSS 重置通常放置在 CSS 样式表的顶部或开始,所以它们首先加载。开发人员通常使用它们来删除浏览器最初给几个元素的默认样式,然后才开始实际设计他们的元素和网站。CSS 重置还可以帮助消除不同浏览器之间的不一致。

CSS 重置是临时的样式,稍后会在样式化过程中更改。然而,根据 CSS 重置中使用的元素或元素组的选择器的简单性或复杂性,稍后在代码中可能很难覆盖初始样式。

例如,假设我们将网站上的所有的 a 标签设置为绿色。然后,我们稍后决定将所有 header 里的 a 标签的样式设置为灰色。

由于在 CSS 重置中选择的复杂性,新的(灰色)样式不会被应用。重置中的选择器比后面代码中仅针对 header 里的 a 标签使用的选择器具有更高阶的优先级,因此没有应用灰色样式。

现在,如果我们将 :where() 伪类函数添加到 CSS 重置中,这将自动为重置中的所有元素赋予零的优先级。这使得我们以后更容易更改样式,而不必担心优先级冲突。

5.2 删除样式
如果想要删除或取消样式或降低一个或一组元素的优先级,则 :where() 函数非常有用。

5.3 保持样式
如果要确保一个元素或元素集的样式或优先级在未来的任何时候都不会改变,那么不要使用 :where() 伪类。

6. 什么是 :is() 函数?

:is() 函数的运行方式几乎与 :where() 函数相同。你可以用它来简化复杂的选择器,也可以把它放在选择器的开头、中间或结尾,就像 :where() 函数一样。
它也是安全的,就像 :where() 函数一样。因此,当其中一个选择器无效时,浏览器将忽略该选择器,但有效选择器的样式将添加到所选元素中。

7. :where() 和 :is() 函数的区别

这两个函数的区别在于 :where() 函数的优先级总是零,则 :is() 函数的优先级取决于其最特定参数的优先级。例如,让我们看看 header 元素中的段落文本:

<header>
  <p>This is a paragraph text.</p>
</header>

然后,让我们尝试使用四种不同的选择器来改变文本颜色:

header p {
  color: blue;
}
:is(header, section) p {
  color: green;
}
p {
  color: blue;
}
:where(header, section) p {
  color: blue;
}

第一个选择器将文本的颜色设置为蓝色。使用 :is() 的第二个选择器与第一个选择器具有相同的优先级,但由于它位于第一个选择器之后,因此它将文本颜色从蓝色更改为绿色。第三个选择器的优先级低于第一个和第二个选择器,对文本没有影响。最后是第四个,它使用 :where() 函数对文本没有影响,因为它的零优先级。

8. 浏览器兼容性

所有浏览器,无论是桌面浏览器还是移动浏览器,都完全支持 CSS :where() 函数,包括对其安全特性的支持。因此,你 不必担心你 的样式是否会在浏览器中正确呈现。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容