• Babel 插件通关秘籍
  • Git 原理详解及实用指南
  • Nest 通关秘籍
  • React 通关秘籍
  • TypeScript 全面进阶指南
  • TypeScript 类型体操通关秘籍
  • 现代CSS
  • Babel 插件通关秘籍
  • Git 原理详解及实用指南
  • Nest 通关秘籍
  • React 通关秘籍
  • TypeScript 全面进阶指南
  • TypeScript 类型体操通关秘籍
  • 现代CSS
  • 现代CSS

    • 01.CSS的父选择器::has()
    • 02.CSS选择器:has()能解决什么问题
    • 03.CSS选择器::has()与:not()的组合
    • 04.CSS选择器::where()vs.:is()
    • 05.CSS焦点样式::focus-visible和:focus-within
    • 06.用于美化模态框的:modal和::backdrop
    • 07.CSSCustomHighlightAPI:Web文本范围高亮的未来
    • 08.画中画:CSS的:picture-in-picture伪类
    • 09.CSS显式默认值:inherit,initial,unset和revert
    • 10.现代CSS中的颜色格式:RGB,HSL,HWB,LAB和LCH
    • 11.新的CSS颜色空间:为Web设置高清颜色
    • 12.CSS中的OKLCH和OKLAB
    • 13.CSS的混合颜色:color-mix()
    • 14.Web控件UI颜色的定制:accent-color和color-scheme
    • 15.颜色对比度:color-contrast()
    • 16.CSS的比较函数:min(),max()和clamp()
    • 17.CSS的三角函数
    • 18.F-mods:可用于@font-face的新特性
    • 19.CSS的text-box-trim和text-box-edge给排版带来的变化
    • 20.Web上的可变字体
    • 21.Web上的彩色字体
    • 22.首字母下沉:initial-letter
    • 23.经典排版技术:使用text-wrap:balance实现文本平衡换行
    • 24.CSS自定义属性你知道多少
    • 25.CSS自定义属性可以用来做些什么
    • 26.现代CSS中的相对单位
    • 27.CSS逻辑属性和逻辑值
    • 28.CSSGrid之瀑布流布局:masonry和masonry-auto-flow
    • 29.CSS媒体查询新特性:@media
    • 30.CSS判断:@supports
    • 31.CSS分层:@layer
    • 32.CSS容器查询之尺寸查询
    • 33.CSS容器查询之样式查询和状态查询
    • 34.CSS的嵌套和作用域:&和@scope
    • 35.CSS计数器:@counter-style
    • 36.CSS自定义属性:@property
    • 37.CSS变换之单个变换
    • 38.CSS宽高比:aspect-ratio
    • 39.CSS的锥形渐变
    • 40.CSS的Clipping和Masking
    • 41.CSS的object-view-box
    • 42.CSS图像处理与特效指南
    • 43.CSS滚动驱动动效
    • 44.CSS路径动画
    • 45.CSS动画合成:animation-composition
    • 46.解锁CSSViewTransitionsAPI的魔力
    • 47.CSS锚点定位:探索下一代Web布局

近年来,CSS 添加了一些全局关键词:inherit 、initial 、unset 和 revert 。理论上,它们可以应用于除 none 以外的任何 CSS 属性。它们在 CSS 中也被称为 CSS 显式默认值,其中 inherit 、initial 和 unset 是在级联层 Level3 (Cascading Level 3)规范中定义的,而 revert 是在级联层 Level4 (Cascading Level 4)中添加的。在 CSS 中,它们可以在属性的默认值或重置属性的值方面提供很多细微的控制。

今天,我们就来简单了解一下这些特殊的 CSS 关键词。同时,我们也将探讨何时使用它们的效果最好,以及它们之间存在的一些重要的区别。

CSS 的基础知识

在我们深入探讨 inherit 、initial 、unset 和 revert 等关键词之前,我们有必要先了解一些 CSS 的基础知识,比如 CSS 属性的初始值、浏览器默认样式表、继承和非继承等。

那我们就先从 CSS 属性的初始值开始!

CSS 属性的初始值

在 CSS 中,每一个 CSS 属性都会有一个属于自己的初始值,即由客户端(比如,浏览器)定义的值。这个值通常在 CSS 规范中为该属性定义。简单地说,你在 W3C 规范中查询任何 CSS 属性,它都会具有一个初始值。如下图所示:

img

即,规范中介绍属性参数时,会有一个名为 “Initial” 选项,该选项对应的值就是 CSS 属性的初始值,也就是 initial 对应的值。例如 font-size 的初始值是 medium ,即:

.font-size {
    font-size: initial;
}

/* 等同于 */
.font-size {
    font-size: medium;
}

这是很重要的,因为在大多数情况下,我们都希望将属性的值重置为其初始值。

浏览器默认(User-Agent)样式表

在所有的 CSS 属性都设置完初始样式之后,紧接着浏览器会加载自身的样式表。该样式表与 CSS 属性的初始值没有任何关系。例如,h1 元素,浏览器给它设置的默认样式如下:

/* user agent stylesheet */
h1 {
    display: block;
    font-size: 2em;
    margin-block-start: 0.67em;
    margin-block-end: 0.67em;
    margin-inline-start: 0px;
    margin-inline-end: 0px;
    font-weight: bold;
}

HTML 元素是没有初始样式值的!上面所示代码中 <h1> 标签元素的基础样式是从“用户代理样式表”(user agent stylesheet)中获取的,而不是 CSS 属性的初始值 initial。

两种属性类型:继承和非继承

CSS 中有两组属性:

  • 继承属性组:由默认情况下从父元素继承定义的属性组成;它们主要是排版属性(如 font-size、color 等)。你可以点击这里查询可继承的 CSS 属性组。
  • 非继承属性组:由其余的属性组成,它们不受父元素的定义影响(比如 margin 、padding 等)。

同样的,在 W3C 描述每个属性的时候,都有明确的描述,该属性是哪种类型的属性:

img

正如上图所示,font-size 属性的 “Inherited” 参数值为 “yes” 时,表示该属性是一个可继承属性;dispaly 和 background-color 属性的 “Inherited” 参数值为 “no”,表示它们是一个非可继承属性。

CSS 的可继承属性是有一种机制的。简单地说,每个 HTML 元素默认有每个 CSS 属性的定义初始值。初始值是一个不可继承的属性,如果级联无法计算元素的值,则会显示为默认值。

可以被继承的属性会向下级联,子元素将获得一个计算值,该计算值代表其父元素的值。这意味着,如果父元素的 font-weight 属性设置为 bold,所有子元素都会是粗体,除非它们的 font-weight 属性被设置为不同的值,或者用户代理样式表为该元素设置了一个 font-weight 值。

也就是说:

  • 当元素的一个继承属性没有指定值时,则取父元素的同属性的计算值,只有文档根元素取该属性的概述中给定的初始值;
  • 当元素的一个非继承属性没有指定值时,则取属性的初始值。

处理 CSS 继承的机制

在 CSS 中提供了几个属性值,可以用来处理 CSS 属性的继承。这几个属性值就是 initial、inherit、unset 和 revert。其实除了这四个属性值之外,还有一个 all 属性值。虽然这几个属性值主要用来帮助大家处理 CSS 属性继承的,但他们之间的使用,还是有一定的差异化。

先用一张图来阐述它们之间的差异:

img

接下来我们一看看这几个属性值的实际使用以及对应的差异化。

initial 的作用是什么?

最容易理解的 CSS 值是 initial。这个值只是将 CSS 属性重置为其初始值,这个初始值在该属性的 W3C 规范中指定。但使用它时,你可能会感到困惑,因为属性的初始 CSS 值并不总是你想象的那样,它通常与浏览器的默认样式不同。

事实上,从 W3C 规范中获取的 CSS 属性初始值也较为混乱。其中有些是合理的,有些是不合理的。例如,CSS 的 float 的初始值是 none ,background-color 的初始值是 transparent ,它们是属性合理的一类。但有一些基本上是任意的。比如 CSS 的 display 属性,为什么初始值就是 inline ,而不是 block 呢?我也不知道当时 CSS 工作小组为什么要这样设计 display 属性,我们只知道 W3C 规范也给 display 定义了一个初始值,虽然 inine 有点奇怪,但 block 同样奇怪。

也就是说,无论如何,initial 关键字**都要**将属性恢复到规范中**定义**的初始值,无论是否合理。

即使 W3C 对 CSS 属性的初始值定义有些混乱或者不合理,但是在一些具体场景中,将 CSS 的属性的值设置为 initial 是非常有益的。比如,你想删除所有特定于浏览器的样式时,使用 initial 值就是非常好的选择。

我们来看一个具体的示例。假设我们有一个<p> 元素:

<p>👧🏼欢迎来到现代 CSS 的世界中🎫</p>

这个 <p> 元素是一个块元素,即 display: block 。

为了好看,咱们添加一点修饰的样式代码:

p {
    background: #f36;
    padding: 2rem;
    font-size: clamp(2rem, 5cqw + 2.25rem, 3rem);
    color: #fff;
    text-shadow: 1px 1px 0.0125em rgb(0 0 0 / 0.5);
}

你在浏览器中看到的效果如下:

img

Demo 地址:https://codepen.io/airen/full/eYPMarJ

如果我们希望 p 元素变成行内元素时,按照我们以前的处理方式,需要手动处理浏览器默认样式(User-Agent 用户代理样式),也就是显示的重置:

p {
    dispaly: inline;
}

block 和 inline 效果对比如下:

img

Demo 地址:https://codepen.io/airen/full/VwEXOGQ

前面提到过 inline 是 display 的初始值(也就是默认值),而在规范中也提到过: 你在元素样式的设置中显示的设置某个属性的值为 initial 时,其实就表示设置了该属性的默认值。 也就是说,我们可以给 display 设置 initial 关键词:

p {
    display: initial;

    /* 等同于将 diplay 重置为 inline */
    display: inline;
}

这个时候得到的效果其实和使用 display:inline 是一样的:

img

Demo 地址:https://codepen.io/airen/full/poxLmBj

使用开发者工具查看相应的计算值,不难发现,display 设置为 initial 时,会覆盖用户代理的样式值 block:

img

接下来,我们再来看一个继承属性 color 的示例。

<p>👧🏼欢迎来到<strong>现代 CSS </strong>的世界中🎫</p>
p {
    background: #f36;
    padding: 2rem;
    font-size: clamp(2rem, 5cqw + 2.25rem, 3rem);
    color: #fff;
    text-shadow: 1px 1px 0.0125em rgb(0 0 0 / 0.5);
}

p strong {
    color: initial;
}

示例中的 color 属性是一个可继承属性,所以 <p> 元素的后代元素 <strong> 也会继承 <p> 元素中设置的color: #fff 值。如果我们显式的在 strong 中设置 color 的值为 initial 时,那么 strong 的 color将重置为默认值。由于我们没有设置默认的 color 颜色,那么这个时候,浏览器将会把一个计算值赋予成color 的初始值:

img

Demo 地址:https://codepen.io/airen/full/abRYgmE

inherit 的作用是什么?

在 CSS 中,许多属性会从其父元素继承值。例如,font-family(字体系列)、color(颜色)和许多其他属性默认情况下会继承其值。这就是为什么你可以将一个 div 元素的文本颜色(color)设置为绿色,并使该 div 的所有子元素文本也都变为绿色。通过将 CSS 属性的值设置为 inherit,你告诉浏览器将该 CSS 属性的值设置为与其父元素的属性值相等。如果父元素也继承该属性的话,它将一直向上寻找,直到找到某个父元素上设置的具体值。

举个例子,如果我给一个 div 元素设置了 5px 的实线蓝色边框(即 border: 5px solid blue),并在该 div 内部放置了一个子元素(比如 p ),那么我们知道边框只会显示在父 div 上,而不会显示在子元素上。

<div>
    <p>👧🏼欢迎来到<strong>现代 CSS </strong>的世界中🎫</p>
</div>
div {
    border: 5px solid #09f;
    padding: 1rem;
}

p {
    background: #f36;
    padding: 2rem;
    font-size: clamp(2rem, 5cqw + 2.25rem, 3rem);
    color: #fff;
    text-shadow: 1px 1px 0.0125em rgb(0 0 0 / 0.5);
}

img

Demo 地址:https://codepen.io/airen/full/vYVRqqB

然而,如果我在子元素 p 上将 border 属性设置为 inherit,那么该子元素也将具有 5px 的实线蓝色边框:

p {
    border: inherit;
}

img

Demo 地址:https://codepen.io/airen/full/NWOYQWp

这是一个非常有用的属性值,因为某些元素(如按钮)在浏览器样式表中有特定的 font-family 设置,但你很可能希望继承该 font-family 以与站点的其余部分保持一致。这就是为什么我几乎总是将按钮的 font-family 设置为 inherit 的原因。

:where(button) {
    font-family: inherit;
}

需要记住的重要一点是,inherit 属性值使元素从其父元素继承其值,而不是从级联中继承其值。比如上面这个示例,如果我们在 p 元素上未显式设置 border 属性的值,即使你在 strong 元素中显式设置 border 的值为 inherit ,它也不会继承其祖父元素 div 的边框样式:

div {
    border: 5px solid #09f;
}

div strong {
    border: inherit;
}

img

Demo 地址:https://codepen.io/airen/full/jOezgVY

这个示例说明:尽管元素自身显式的设置了 inherit 关键词,但是,如果其父元素没有明确指定样式,那么其最终效果将和 revert 的效果一致。即继承的是其父元素的计算值,也就是浏览器默认样式(User Agent Stylesheet)。

前面我们提到过,CSS 的属性会可继承和不可继承两种类型,对于可继承属性,它是会自动继承其父元素对应的属性值。比如 color 属性,默认情况之下会继承其父元素的 color 值。来看一个具体的例子:

<div class="box"><strong>Color</strong>是一个可继承属性</div>
.box {
    color: #fff;
}

理论上,你是不需要在 <strong> 元素上显式设置 color 属性的值,它的文本颜色也是 #fff 。虽然说,color 属性是可继承属性,但也并不意味着它总是会继承其父元素的 color 属性值。因为,有的时候它和客户端(比如,浏览器)设置的默认值也是有关系的。比如,将上面示例中的 <strong> 换成 <a> 元素,要是你没有将 <a> 元素的 color 属性值设置为 inherit ,即使 color 是可继承属性,它的颜色也不会是 #fff (不会继承其父元素的 color 属性值)。这是因为浏览器自动将 <a> 元素的 color 值设置为蓝色。

<div class="box">
    <a href="">我是一个链接元素</a>,我的 color 并不会自动继承父元素的 color 值
</div>
.box {
    color: #fff;
}

img

这种现象在 CSS 中很常见,比如 mark 标签也和 a 标签类似。但是,要是你在 a 和 mark 元素上显式将 color 属性的值设置为 inherit 时,结果就会不一样了:

.box a,
.box mark {
    color: inherit;
}

它会明确告诉浏览器,a 和 mark 的文本颜色 color 要继承其父元素 .box 的 color 值。在我们这个示例中,a 和 mark 的文本颜色都将变成白色(#fff):

img

Demo 地址:https://codepen.io/airen/full/XWxqzmM

无论如何,这就是 inherit 关键字的工作原理。在字体大小或颜色方面使用它可能偶尔是一个好主意,但其他情况下少使用。并且请记住继承和非继承属性之间的差异,稍后这将变得很重要。

unset 的作用是什么?

unset 是一个有趣的属性值,因为它会执行与 initial 或 inherit 相同的操作。换句话说,unset 关键词可以重置可继承和不可继承的属性。

  • 如果一个 CSS 属性本来就是继承的,比如 color、font-family等,那么它(unset)将像 inherit 一样执行。
  • 如果一个 CSS 属性本来就是不可继承的,比如 display、border等,那么它(unset)将像 initial 一样执行。

也就是说,在任何属性上使用 unset 关键词将会应用其适当的重置关键词。例如:

.box {
    max-width: unset; /* unset = initial = none */
    font-size: unset; /* unset = inherit = 父元素的 font-size 值 */
}

起初 unset 关键词似乎并不是很有用,因为你可以手动将 inherit 或 initial 作为属性的重置值,但是随着 all 属性出现,unset 就变得非常有用。就拿上面的代码为例,现在你可以直接将 all 设置为 unset 即可:

.box {
    all: unset;
}

/* 等同于 */
.box {
    max-width: unset; /* unset = initial = none */
    font-size: unset; /* unset = inherit = 父元素的 font-size 值 */
}

通过使用 all,我们可以将元素的所有内容重置为初始值或确保它们继承,这在从头开始创建 HTML 元素的样式时非常理想。例如,如果你想从一个按钮(<button>)元素中删除所有浏览器特定的样式,这就非常有用了。

或者说,一个元素运用了很多属性,你希望能够确保它们全部重置,而无需逐个进行操作。例如,你正在使用一个第三方库(比如 Bootstrap)中的按钮 .button ,但你在某个场景下,需要重置第三方库赋予的所有样式,那么使用 all:unset 就非常有用。

.btn-secondary {
    all: unset;
}

img

Demo 地址:https://codepen.io/airen/full/PoyeOgq

不过,这几乎是 unset 的唯一用例。

然而,在某些情况下,将 CSS 恢复到其默认值是不够的。例如,如果我们将一个 <div> 元素的 display 属性重置为 unset,我们得到的初始值(initial)将是 inline 而不是 block。示例:

div {
    display: unset; /* = initial = inline */
}

此时,inline 的值将应用于 div 元素。

事实上,客户端(比如浏览器)在渲染 HTML 元素时,对于块元素(例如,<div> 、<p> 等),display 属性的初始值为 block,但对于内联元素(例如 <span> 和 <a>),display 的初始值为 inline。如果仅是将元素的 display 属性被设置为 unset,它将最终以 inline 的方式渲染,这是因为初始值(initial)没有使用浏览器的 User-agent-stylesheet 中的默认样式。

revert 的作用是什么?

作为一名 Web 开发者,我想你在对一个 Web 应用或页面开始编写 CSS 的时候,都会先重置客户端(如浏览器)所提供的默认样式。那么,关键词 revert 就显得尤其的重要,因为它允许将 CSS 属性的值重置回浏览器特定的样式。例如,一个元素的 CSS 样式已经被大量修改,你想将其中的一部分或全部样式更改回浏览器默认样式,那么可以将属性值设置为 revert 。

我并不经常使用这个功能,因为我更喜欢删除所有浏览器样式,但在使用 all: unset 后,将一些样式更改回浏览器特定的样式可能会很有用。revert 关键字首先确定浏览器的 User-agent-stylesheet (浏览器加载的默认 CSS 文件)是否为特定的 HTML 元素创建特殊样式。如果是,则将重置为这些默认样式。例如:

div {
    display: revert; /* = block */
}

span {
    display: revert; /* = inline */
}

table {
    display: revert; /* = table */
}

如果 User-agent-stylesheet (浏览器加载的默认 CSS 文件)中没有为该元素定义样式,则 revert 关键字的行为将类似于 unset 值。如果属性属于继承组,则将其重置为 inherit 值;否则,将其重置为 initial。

也就是说,revert 也区分了可继承属性和不可继承属性:

  • 如果一个属性通常是可继承的,revert 的含义就是继承
  • 如果一个属性通常不可继承,revert 将还原为浏览器样式表中指定的值

如果你想将应用程序中的每个元素,使其回到浏览器的默认样式,则可以选择使用 all: revert ,即:

* {
    all: revert;
}

实际上,应用程序内的每个元素都像是从头开始一样!

revert vs. unset

revert 和 unset 非常像,唯一的区别在于 revert 会把 CSS 属性值重置为 User-agent-stylesheet (浏览器加载的默认 CSS 文件)中对应的值,例如:

/* unset */
div {
    display: unset; /* = initial = inline */
}

h1 {
    font-weight: unset; /* = inherit = 其父元素的 font-weight 的值 */
    font-size: unset; /* = inherit = 其父元素的 font-size 的值  */
}

/* revert */
div {
    display: revert; /* = block = User-agent-stylesheet */
}

h1 {
    font-weight: revert; /* = bold = User-agent-stylesheet */
    font-size: revert; /* = 2em = User-agent-stylesheet */
}

总之,unset 和 revert 的主要区别在于 revert 考虑了用户定义和开发者编写的样式,而 unset 只考虑继承。因此,如果你想将属性重置为其继承(inherit)或初始(initial)值,并考虑用户定义或开发者编写的样式,请使用 revert。如果你只想将属性重置为其继承(inherit)或初始(initial)值,并且不需要考虑用户定义或开发者编写的样式,请使用 unset。

initial VS. inherit VS. unset VS. revert

我们花了一些篇幅向大家阐述了 initial 、inherit 、unset 和 revert 几个关键词的作用和功能是什么以及何时使用哪个关键词。但我还是希望一个示例,向大家阐述它们之间的差异之处。比如,下面这个示例:

<div>
    <h2>Title</h2>
</div>
div {
    color: red;
    border: 5px solid green;
    margin: 10px;
    padding: 10px;
}

h2 {
    color: blue;
}

我们分别在 div 和 h2 元素上应用了一些简单的 CSS 样式。在浏览器中呈现的效果如下图所示:

img

Demo 地址:https://codepen.io/airen/full/OJBZZwm

其中 color 是可继承属性,border 、margin 和 padding 是不可继承属性。例如,div 元素各属性的具体描述如下所示:

属性名初始值是否可继承User Agent Style(浏览器默认样式)开发者编写样式
color取决于用户代理✔blackred
border-colorcurrentColor✘Nogreen
border-widthmedium✘No5px
border-style取决于计算值✘Nosolid
margin0✘No10px
padding0✘No10px

h2 元素各属性具体描述如下所示:

属性名初始值是否可继承User Agent Style(浏览器默认样式)开发者编写样式
color取决于用户代理✔blackblue
border-colorcurrentColor✘NoNo
border-widthmedium✘NoNo
border-style取决于计算值✘NoNo
margin0✘0.83em 0pxNo
padding0✘NoNo

如果给 h2 元素添加下面这段代码:

h2 {
    color: inherit;
    border: inherit;
    margin: inherit;
    padding: inherit;
}

img

Demo 地址:https://codepen.io/airen/full/YzJLvVQ

很明显,h2 元素继承了其父元素 div 的 color 、border 、margin 和 padding 。即:

属性名开发者编写样式(值)计算值继承值来源
colorinheritred父元素 div
border-colorinheritgreen
border-widthinherit5px
border-styleinheritsolid
margininherit10px
paddinginherit10px

将上面代码中的 inherit 值替换为 initial ,即 h2 元素中的 color 、border 、padding 和 margin 都为初始值:

h2 {
    color: initial;
    border: initial;
    margin: initial;
    padding: initial;
}

img

Demo 地址:https://codepen.io/airen/full/QWZrxQo

属性名初始值开发者编写样式(值)计算值值来源
colorCanvasTextinitialblack初始值
border-colorcurrentColorinitialcurrentColor初始值
border-widthmediuminitial5px初始值
border-stylenoneinitialnone初始值
margin0initial0初始值
padding0initial0初始值

继续把 h2 中的 color 、padding 、margin 和 border 属性的值重置为 unset :

h2 {
    color: unset;
    border: unset;
    margin: unset;
    padding: unset;
}

你将看到的效果如下:

img

Demo 地址:https://codepen.io/airen/full/LYgmrgL

前面说过了,unset 会根据属性是否为可继承属性来做判断。如果属性是可继承属性,那么 unset 相当于 inherit,比如 color ,则 h2 的 color 会继承父元素 div 的 color 值;如果属性是不可继承属性,那么 unset 相当于 initial ,比如 border 、padding 和 margin 都是不可继承属性,所以 h2 上的 border 、padding 和 margin 都会取它们各自的初始值 initial :

属性名初始值是否可继承User Agent Style(浏览器默认样式)开发者编写样式计算值值来源
colorCanvasText✔blackunsetred继承父元素 div 的 color 值
border-colorcurrentColor✘NounsetcurrentColor初始值
border-widthmedium✘Nounsetmedium初始值
border-stylenone✘Nounsetnone初始值
margin0✘0.83em 0pxunset0初始值
padding0✘Nounset0初始值

最后再来看 revert 关键词,把 h2 中的 color 、border 、margin 和 padding 等属性的值设置为 revert :

h2 {
    color: revert;
    border: revert;
    margin: revert;
    padding: revert;
}

此时看到的效果如下图所示:

img

Demo 地址:https://codepen.io/airen/full/OJBZwVq

revert 会将属性重置为其父级自然继承的值。在我们的例子中,它从父级 div 继承了 color。如果该属性不是可继承属性,则 revert 会将级联值回退到先前的级别。如果存在用户代理或用户默认样式,则将属性设置为默认值。在我们的例子中,它将 h2 的 margin 设置为其用户代理默认值 0.83em。如果没有默认样式,则将值设置为其初始值。这适用于我们示例中的边框属性。

属性名初始值是否可继承User Agent Style(浏览器默认样式)开发者编写样式计算值值来源
colorCanvasText✔blackrevertred继承父元素 div 的 color 值
border-colorcurrentColor✘NorevertcurrentColor初始值
border-widthmedium✘Norevertmedium初始值
border-stylenone✘Norevertnone初始值
margin0✘0.83em 0pxrevert0.83em 0px浏览器默认样式
padding0✘Norevert0初始值

简而言之,initial 将值设置为属性的定义初始值,inherit 将值设置为父元素的值,unset 将属性值恢复到继承值或初始值,revert 将属性重置为父级自然继承的值。

all 的作用是什么?

有时候我需要为网站的特定组件设计样式,但我需要重用已经以不同方式进行样式化的类名。当无法使用代码拆分时,这可能导致从其他源继承某些样式,我需要为我的组件覆盖这些样式。例如,假设我们有一个使用 Materialize 进行样式化的按钮,但我需要创建一个完全不同样式的按钮:

img

Demo 地址:https://codepen.io/airen/full/oNaddvV

.unstyled,
.unstyled:hover {
    color: revert;
    background: revert;
    transition: initial;
    cursor: initial;
    text-decoration: revert;
    text-align: initial;
    letter-spacing: initial;
    font-size: revert;
    outline: initial;
    border: initial;
    border-radius: initial;
    display: initial;
    line-height: initial;
    padding: initial;
    text-transform: initial;
    vertical-align: initial;
    box-shadow: initial;
}

Materialize 的按钮有许多样式,虽然最好的方法是使用不同的类来移除它们,但可能存在这样的情况,你没有这个选项,只能选择逐行调整每个属性或使用 all 属性。all 属性将允许你一次性重置多行:

.unstyled-all,
.unstyled-all:hover {
    all: revert;
}

all 属性将所有属性的值重置为给定的值。它目前接受四个值:initial、inherit、revert 和 unset。这些值也可以用作任何其他 CSS 属性的值,以将其重置为特定状态,但如果你确实需要重置所有内容,可以使用 all。

需要再次强调的是,all 可能不是从元素中删除样式的最佳方法。更有效的方法是更新你的选择器,使样式不会被覆盖或使用代码拆分。我只建议在受到应用样式方式和顺序限制时使用 all。

另外,需要注意的是,all 在 CSS 中有时候是一个属性,比如这里说的就是属性,但有的时候它还是 CSS 中某些属性的值。比如我们常在 transition 中用到的 all,那这个时候就是属性值。到目前为止,CSS 中的 all 属性也得到了众多浏览器的支持。

综合案例:创建重置 CSS

现在 CSS 有了这些新的重置功能,即 initial 、inherit 、unset 、revert 和 all ,使得我们创建一个重置 CSS 样式比以前简单得多。

在大部分情况下,我们希望将大多数属性重置为它们的默认初始值或 CSS 的内在行为,使用 unset 值。但正如我们上面所看到的,我们还想保留来自客户端(User-agent-stylesheet)的样式,比如 display 属性。那么我们就可以这样做:

/* 重置除了 `display` 属性之外的所有 User-Agent-Stylesheet 样式 */
* {
    all: unset;
    display: revert;
}

看上去很完美,但还有一些细节需要处理。

当一些特殊的 HTML 元素(例如,<img> 、<video> 、<svg> 、<canvas> 和 <iframe> )的 width 和 height 属性被 all: unset 重置时,这些元素上的 width 和 height 属性的效果也被重置。将会造成这些元素的大小属性不再起作用。

为了解决这个问题,你可以使用一些 CSS 伪类,比如前面课程《CSS 选择器 :has() 和 :not() 的组合》中提到的 :not() 伪类函数。即,将这些元素(比如,img 、video 、svg 、canvas 、iframe 等)当作 :not() 伪类函数的参数:

*:not(img, video, svg, canvas, iframe):not(svg *) {
    all: unset;
    display: revert;
}

但是,使用 :not() 伪类函数会产生一个意想不到的后果,它会增加选择器权重,因此可能会覆盖项目中稍后定义的样式。例如:

*:not(img, svg, video, iframe, canvas):not(svg *) {
    all: unset;
    display: revert;
}

body {
    width: 100vw;
    min-height: 100vh;
    font-family: "Exo", "Bungee Shade", cursive, Arial, sans-serif;
    background-color: #557;
    color: #fff;
    display: grid;
    place-content: center;
    padding: 1rem;
}

div {
    color: red;
    font-size: clamp(2rem, 3vw + 2.5rem, 3rem);
}

img

Demo 地址: https://codepen.io/airen/full/BaqVoOB

其中 *:not(img, svg, video, iframe, canvas):not(svg *) 的权重是 (0, 0, 2) ,而 body 和 div 的权重是 (0, 0, 1) :

img

这就是 body 和 div 选择器对应的样式没有起作用的原因。如果你不希望这种现象出现,可以使用 CSS 的 :where() 伪类选择器,将 *:not(img, svg, video, firame, canvas):not(svg *) 选择器权重除至最低,即 (0 , 0, 0) 。你可以像下面这样做:

*:where(:not(img, svg, video, iframe, canvas):not(svg *)) {
    all: unset;
    display: revert;
}

如果你不想重置一些表单元素,则可以将其 all 属性设置为 revert 。比如 @Elad Shechter 的 《The New CSS Reset》就有这些关键词的使用:

*:where(
        :not(html, iframe, canvas, img, svg, video, audio):not(svg *, symbol *)
    ) {
    all: unset;
    display: revert;
}

a,
button {
    cursor: revert;
}

textarea {
    white-space: revert;
}

meter {
    -webkit-appearance: revert;
    appearance: revert;
}

:where(pre) {
    all: revert;
}

::placeholder {
    color: unset;
}

::marker {
    content: initial;
}

:where(dialog:modal) {
    all: revert;
}

上面代码来源于:https://elad2412.github.io/the-new-css-reset/

当然,你也可以采用更为激进的做法,将 all 属性的值设置为 initial 。其中差别是,initial 使用 CSS 规范上基于每个属性定义的初始值,而 revert 是用户代理样式表根据 CSS 选择器设置的默认值。例如,display 的初始值是 inline (即 initial = inline),而普通用户代理样式表将块元素(比如 div)的默认 display 值设置为 block ,将 table 元素的 display 值设置为 table ,等等。

小结

在 CSS 中,有一些全局关键字( initial、inherit、unset 和 revert)可以用于设置属性的默认值或重置属性的值。虽然它们都可以用于任何属性,但它们之间存在一些重要的区别:

  • initial 会将属性设置为其初始值,即由浏览器定义的值。这个值通常在 CSS 规范中为该属性定义。
  • inherit 将属性设置为其父元素的值。如果没有继承值,则将使用该属性的初始值。
  • unset ,如果属性可以继承,则将属性设置为其继承值(等同于 inherit)。否则,将使用该属性的初始值(等同于 initial )。这意味着 unset 允许继承,并且适用于将属性重置为其默认值,同时仍然允许从父元素继承。
  • revert 与 unset 类似,如果属性可以继承,则将属性设置为其继承值。否则,将使用该属性的初始值。不同之处在于,revert 还考虑了任何用户定义的样式或作者样式表可能应用于元素。如果没有用户定义或作者样式,则 revert 的行为与 unset 相同。

img

而 all 既可以是一个值,也可以是一个属性。只不过,我们这节课所探讨的 all 只是一个属性。或者更确切地说,是元素上所有 CSS 属性的集合。它的值可以是前面所讨论的关键字中的任何一个,并允许你将该关键字应用于所有 CSS 属性。

除此之外,在 W3C 的 CSS Cascading and Inheritance Level 5 规范中新增了一个 revert-layer 关键词。它可以让你回滚到之前的层级中指定的样式。理想情况下,revert-layer 关键词适用于在一个层级内部应用于属性。然而,如果将 revert-layer 关键词设置在一个层级外的属性上,那么该属性的值将回滚到用户代理样式表(或用户样式,如果存在)建立的默认值。因此,在这种情况下,revert-layer 关键词的行为类似于 revert 关键词。

这节课没有对 revert-layer 做过多阐述,我们将会在介绍 @layer 的时候,详细阐述该关键词的具体使用。

最后,再次强调一下,initial 、inherit 、unset 、revert 和 all 要是用好了的话,可以使你的代码更为简洁和灵活性更强,甚至起到事半功倍的效果。

上次更新: 6/21/25, 9:42 AM
贡献者: YNight
Prev
08.画中画:CSS的:picture-in-picture伪类
Next
10.现代CSS中的颜色格式:RGB,HSL,HWB,LAB和LCH