CSS 封装:2023 年!
跳转到内容:
哇!2023 年对 CSS 来说是硕果累累的一年!
从 #Interop2023 到 CSS 和界面领域的许多新发布,这些发布都实现了开发者曾经认为在 Web 平台上不可能实现的功能。现在,所有现代浏览器都支持容器查询、子网格、:has()
选择器以及一系列新的颜色空间和函数。Chrome 支持仅使用 CSS 的滚动驱动型动画,并支持使用视图转场在网页视图之间流畅地呈现动画效果。最重要的是,我们还推出了许多新基元,以便提供更好的开发者体验,例如 CSS 嵌套和作用域样式。
今年真是非比寻常的一年!因此,在这一里程碑之年结束之际,我们想向浏览器开发者和网络社区致敬,感谢他们为此付出的辛勤努力。
架构基础知识
我们先来看看核心 CSS 语言和功能的更新。这些功能对于您编写和整理样式的方式至关重要,并可为开发者提供强大的功能。
三角函数
Chrome 111 添加了对三角函数 (sin()
、cos()
、tan()
、asin()
、acos()
、atan()
和 atan2()
) 的支持,使其可在所有主要引擎中使用。这些函数对于动画和布局目的来说非常方便。例如,现在,您可以更轻松地在选定中心周围的圆形上排列元素。
详细了解 CSS 中的三角函数。
复杂的“第 * 个”选择
浏览器支持
借助 :nth-child()
伪类选择器,您可以按索引选择 DOM 中的元素。使用 An+B
微语法,您可以精细地控制要选择哪些元素。
默认情况下,:nth-*()
伪元素会将所有子元素考虑在内。从 Chrome 111 开始,您可以选择将选择器列表传入 :nth-child()
和 :nth-last-child()
。这样,您就可以在 An+B
执行操作之前预先过滤子项列表。
在以下演示中,3n+1
逻辑仅应用于小娃娃,方法是使用 of .small
预先滤除小娃娃。使用下拉菜单动态更改所使用的选择器。
详细了解复杂的“第 * 个”选择。
范围
Chrome 118 添加了对 @scope
的支持,这是一种 at-rule,可让您将选择器匹配范围限定为文档的特定子树。借助作用域样式,您可以非常具体地选择要选择的元素,而无需编写过于具体的选择器或将其与 DOM 结构紧密耦合。
作用域型子树由作用域根(上限)和可选的作用域边界(下限)定义。
@scope (.card) { … } /* scoping root */
@scope (.card) to (.card__content) { … } /* scoping root + scoping limit*/
放置在作用域块内的样式规则将仅定位到划出的子树中的元素。例如,以下作用域限定的样式规则仅定位到位于 .card
元素和 [data-component]
选择器匹配的任何嵌套组件之间的 <img>
元素。
@scope (.card) to ([data-component]) {
img { … }
}
在以下演示中,由于应用了限定范围限制,轮播界面组件中的 <img>
元素不匹配。
范围演示屏幕截图
Scope 实时演示
如需详细了解 @scope
,请参阅“如何使用 @scope
限制选择器的覆盖面”一文。在本文中,您将了解 :scope
选择器、如何处理特异性、无前缀作用域,以及级联会如何受到 @scope
的影响。
嵌套
在嵌套之前,每个选择器都需要单独显式声明。这会导致重复、批量提供样式表以及零散的创作体验。现在,选择器可以继续使用分组在内的相关样式规则。
dl {
/* dt styles */
dt {
/* dl dt styles */
}
dd {
/* dl dd styles */
}
}
/* same as */
dt {
/* dt styles */
}
dl dt {
/* dl dt styles */
}
dl dd {
/* dl dd styles */
}
嵌套屏幕录制
嵌套实时演示
嵌套可以减小样式表格的大小、减少重复选择器的开销,并集中管理组件样式。语法最初发布时存在一项限制,即必须在各种位置使用 &
,但自发布以来,我们通过嵌套式语法更新取消了该语法。
详细了解嵌套。
子网格
借助 CSS subgrid
,您可以创建更复杂的网格,并在子布局之间实现更好的对齐。它允许另一个网格内的网格通过使用 subgrid
作为网格行或列的值,将外部网格的行和列作为自己的行和列。
子网格抓屏
子网格实时演示
子网格对于将同级元素对齐到彼此的动态内容特别有用。这样一来,文案撰写者、用户体验文案撰写者和译者就不必再尝试制作“适合”于布局的项目文案。借助子网格,您可以调整布局以适应内容。
详细了解 subgrid。
排版
2023 年,Web 排版发生了一些重大更新。text-wrap
属性是一项非常实用的渐进式增强功能。此属性可让您调整排版布局,由浏览器编写,无需其他脚本。告别不协调的行长,拥抱更可预测的排版!
Initial-letter
initial-letter
属性是 Chrome 110 年初推出的一项小巧但功能强大的 CSS 功能,可用于设置首字母的放置样式。您可以将字母放置在下沉或上浮状态。此属性接受两个参数:第一个参数用于指定将字母放置在相应段落中的深度,第二个参数用于指定将字母放置在相应段落上方的位置。您甚至可以将两者结合使用,如以下演示所示。
首字母屏幕截图
首字母演示
详细了解 initial-letter。
text-wrap: balance and pretty
作为开发者,您不知道标题或段落的最终大小、字号甚至语言。有效且美观地处理文本换行所需的所有变量均位于浏览器中。由于浏览器确实知道字体大小、语言和分配区域等所有因素,因此非常适合处理高级且高质量的文本布局。
这时,我们可以使用两种新的文本换行技术,分别称为 balance
和 pretty
。balance
值旨在创建和谐的文本块,而 pretty
旨在防止孤行和确保合理的断词。这两项任务传统上都是手动完成的,现在能够交给浏览器来完成,并且适用于任何翻译语言,这真是太棒了。
文本换行屏幕录制
文本换行实时演示
详细了解 text-wrap: balance。
颜色
2023 年是该网络平台色彩的一年。借助支持动态配色的新颜色空间和函数,您可以随心所欲地为用户打造鲜艳丰富的主题,并使其可自定义!
高清色彩空间(色彩级别 4)
从硬件到软件,从 CSS 到闪烁的灯光,计算机需要付出大量努力,才能尽可能准确地呈现人眼可见的颜色。2023 年,我们将推出新颜色、更多颜色、新的颜色空间、颜色函数和新功能。
CSS 和颜色现在可以:
- 检查用户屏幕硬件是否支持广色域 HDR 颜色。
- 检查用户的浏览器能否理解 Oklch 或 Display P3 等颜色语法。
- 以 Oklab、Oklch、HWB、Display P3、Rec.2020、XYZ 等格式指定 HDR 颜色。
- 使用 HDR 颜色创建渐变,
- 在其他色彩空间中插值渐变。
- 使用 color-mix()
混合颜色。
- 使用相对颜色语法创建颜色变体。
颜色 4 抓屏
Color 4 演示
详细了解 Color 4 和色彩空间。
color-mix 函数
混合颜色是一项传统任务,而 CSS 在 2023 年也可以做到。您不仅可以将白色或黑色混合到某种颜色中,还可以将透明度加入到某个颜色中,并且可以在您选择的任何颜色空间中完成所有这些操作。它既是一项基本色彩功能,也是一项高级色彩功能。
color-mix() 屏幕录制
color-mix() 演示
您可以将 color-mix()
视为梯度中的某个时间点。渐变显示从蓝色变为白色的所有步骤,而 color-mix()
只显示其中一步。当您开始考虑色彩空间并了解混合色彩空间对结果的影响时,就会发现事情变得更加复杂。
详细了解 color-mix()。
相对颜色语法
相对颜色语法 (RCS) 是用于创建颜色变体的补充方法,与 color-mix()
相辅相成。它比 color-mix() 稍强大,但也是处理颜色的另一种策略。color-mix()
可能会混入白色来使颜色变浅,其中 RCS 可精确访问亮度通道,并能够对通道使用 calc()
以程序化方式减小或增大亮度。
RCS 屏幕录制
RCS 实时演示
借助 RCS,您可以对颜色执行相对和绝对操作。相对变化是指获取饱和度或亮度的当前值,并使用 calc()
进行修改。绝对更改是指将通道值替换为全新的值,例如将不透明度设置为 50%。借助此语法,您可以使用有意义的工具来设置主题、实时变体等。
详细了解相对颜色语法。
自适应设计
自适应设计在 2023 年得到了演变。这一突破性年份推出了一些新功能,彻底改变了我们构建自适应 Web 体验的方式,并开创了基于组件的自适应设计新模式。容器查询和 :has()
的组合支持根据父级的大小以及任何子级的存在或状态,为组件提供自适应逻辑样式。这意味着,您终于可以将页面级布局与组件级布局分离开来,只需编写一次逻辑即可在任何地方使用组件!
大小容器查询
容器查询支持查询网页中的父元素,而不是使用视口的全局大小信息来应用 CSS 样式。这意味着,组件可以在多个布局和多个视图中以动态方式设置样式。今年情人节(2 月 14 日),所有新式浏览器中针对尺寸的容器查询都已稳定。
如需使用此功能,请先在要查询的元素上设置容器,然后(与媒体查询类似),将 @container
与尺寸参数结合使用以应用样式。除了容器查询之外,您还会获得容器查询大小。在以下演示中,容器查询大小 cqi
(表示内嵌容器的大小)用于设置卡片标题的大小。
@container 屏幕录制
@container 演示
详细了解如何使用容器查询。
样式容器查询
在 Chrome 111 中,样式查询已部分实现。目前,使用样式查询时,您可以使用 @container style()
查询父元素上的自定义属性的值。例如,查询某个自定义属性值是否存在,或者设置为某个值(如 @container style(--rain: true)
)。
样式查询屏幕截图
样式查询演示
这听起来与在 CSS 中使用类名称类似,但样式查询有一些优势。首先,通过样式查询,您可以根据伪状态的需要更新 CSS 中的值。此外,在未来的实现版本中,您将能够查询值范围,以确定应用的样式(例如 style(60 <= --weather <= 70)
)以及基于属性-值对(例如 style(font-style: italic)
)的样式。
详细了解如何使用样式查询。
:has() 选择器
近 20 年来,开发者一直在要求 CSS 中提供“父级选择器”。现在,借助 Chrome 105 中随附的 :has()
选择器,即可实现这一点。例如,使用 .card:has(img.hero)
将选择具有主推图片作为子元素的 .card
元素。
:has() 演示屏幕截图
:has() 实时演示
由于 :has()
接受相对选择器列表作为参数,因此您可以选择的不仅仅是父元素。使用各种 CSS 组合符,不仅可以向上遍历 DOM 树,还可以进行横向选择。例如,li:has(+ li:hover)
将选择当前悬停的 <li>
元素之前的 <li>
元素。
:has() 屏幕演示
:has() 演示
详细了解 CSS :has()
选择器。
更新媒体查询
借助 update
媒体查询,您可以根据设备的刷新率调整界面。该功能可以报告值 fast
、slow
或 none
,该值与不同设备的功能相关。
您设计的大多数设备都可能具有较高的刷新率。这包括桌面设备和大多数移动设备。电子阅读器和低功耗付款系统等设备的刷新率可能较慢。知道设备无法处理动画或频繁更新,这意味着您可以节省电量消耗或减少错误的视图更新。
更新抓屏
更新演示
详细了解 @media(更新)。
使用脚本编写媒体查询
脚本媒体查询可用于检查 JavaScript 是否可用。这非常适合渐进式增强。在此媒体查询之前,检测 JavaScript 是否可用的方法是将 nojs
类放入 HTML 中,然后使用 JavaScript 将其移除。由于 CSS 现在可以检测 JavaScript 并相应地进行调整,因此可以移除这些脚本。
请点击此处,了解如何通过 Chrome 开发者工具在网页上启用和停用 JavaScript 以进行测试。
脚本屏幕演示
脚本演示
假设某个网站上的主题切换,由于没有 JavaScript 可用,因此脚本媒体查询有助于使该切换针对系统偏好设置发挥作用。或者,考虑一下开关组件:如果 JavaScript 可用,则可以使用手势滑动开关,而不仅仅是开启和关闭开关。如果可使用脚本,则有很多机会升级用户体验;如果脚本已停用,则可以提供有意义的基础体验。
详细了解脚本。
降低透明度的媒体查询
非不透明界面可能会引起头痛或因各种类型的视觉缺陷而造成视觉疲劳。因此,Windows、macOS 和 iOS 都提供了系统偏好设置,可减少或移除界面的透明度。适用于 prefers-reduced-transparency
的此媒体查询与其他偏好媒体查询非常契合,可让您在发挥创意的同时,根据用户进行调整。
“降低透明度”屏幕录制
降低透明度演示
在某些情况下,您可以提供一种替代布局,其中不会有内容叠加在其他内容上。在其他情况下,可以将颜色的不透明度调整为不透明或几乎不透明。以下博文提供了更多鼓舞人心的演示,这些演示可以适应用户偏好,如果您想知道此媒体查询何时具有价值,不妨看看他们。
交互
互动是数字体验的基石。它有助于用户了解自己点击了什么,以及自己在虚拟空间中的所在位置。今年,我们发布了许多激动人心的功能,这些功能简化了交互的编写和实现,从而实现顺畅的用户体验历程和更精细的网络体验。
视图过渡
视图转换对网页的用户体验有很大影响。借助 View Transitions API,您可以在单页应用的两种页面状态之间创建视觉过渡。这些过渡可以是整页过渡,也可以是页面上的较小内容(例如向列表中添加或移除新项)。
View Transitions API 的核心是 document.startViewTranstion
函数。传入用于将 DOM 更新为新状态的函数,API 会为您处理一切。它通过拍摄前后对比的快照,然后在两者之间进行过渡来实现此目的。您可以使用 CSS 控制要捕获的内容,并根据需要自定义这些快照的动画方式。
VT 抓屏
VT 演示
适用于单页应用的 View Transitions API 已在 Chrome 111 中发布。详细了解视图过渡。
线性缓动函数
浏览器支持
不要被此函数的名称欺骗到。借助 linear()
函数(不要与 linear
关键字混淆),您可以通过简单的方式创建复杂的加/减速函数,但会牺牲部分精度。
在 Chrome 113 中发布的 linear()
之前,无法在 CSS 中创建弹跳或弹簧效果。借助 linear()
,您可以将这些缓动效果简化为一系列点,然后在这些点之间进行线性插值,以近似地实现这些缓动效果。
线性加/减速抓屏
线性缓动演示
滚动结束
许多界面都包含滚动互动,有时界面需要同步与当前滚动位置相关的信息,或根据当前状态提取数据。在 scrollend
事件之前,您必须使用不准确的超时方法,该方法可能会在用户的手指仍在屏幕上时触发。借助 scrollend
事件,您可以获得精准的时间滚动结束事件,以了解用户是否仍在执行手势。
滚动屏幕抓屏
Scrollend 演示
这对浏览器来说非常重要,因为 JavaScript 无法跟踪滚动期间手指在屏幕上的存在情况,因为系统根本无法获取相关信息。现在,您可以删除大量不准确的滚动结束尝试代码,并将其替换为浏览器拥有的高精度事件。
详细了解 scrollend。
滚动条驱动的动画
滚动条驱动的动画是 Chrome 115 中推出的一项令人兴奋的功能。借助这些方法,您可以使用现有的 CSS 动画或使用 Web 动画 API 构建的动画,并将其与滚动条的滚动偏移量相关联。当您上下滚动(或在水平滚动条中向左或向右滚动)时,关联的动画将直接响应并向前或向后拖动。
您可以使用 ScrollTimeline 来跟踪滚动条的总体进度,如以下演示所示。当您滚动到页面底部时,文字会逐字显示。
SDA 抓屏
SDA 演示
借助 ViewTimeline,您可以跟踪元素穿过滚动边界的情况。这与 IntersectionObserver 跟踪元素的方式类似。在以下演示中,从进入滚动窗口到位于中心,每个图片都会逐渐显示出来。
SDA 演示版抓屏
SDA 现场演示
由于滚动驱动型动画可与 CSS 动画和 Web Animations API 搭配使用,因此您可以获享这些 API 带来的所有优势。这包括能够在主线程之外运行这些动画。现在,只需再添加几行代码,即可实现由滚动驱动的平滑动画,让动画在主线程之外运行。有没有什么不喜欢呢?
如需详细了解滚动条驱动的动画,请参阅本文了解所有详情或访问 scroll-driven-animations.style,其中包含许多演示。
延迟的时间轴附件
通过 CSS 应用滚动驱动型动画时,用于查找控制滚动条的查找机制始终会沿 DOM 树向上遍历,因此仅限于滚动祖先。不过,很多情况下,需要添加动画效果的元素并非滚动条的子元素,而是位于完全不同的子树中的元素。
如需允许动画元素查找非祖先的命名滚动时间轴,请对共享父元素使用 timeline-scope
属性。这样一来,便可将已定义的 scroll-timeline
或具有该名称的 view-timeline
附加到其中,从而实现更广泛的范围。完成后,该共享父级的任何子级都可以使用该名称的时间轴。
演示版抓屏
实时演示
详细了解 timeline-scope
。
离散属性动画
2023 年的另一项新功能是能够为离散动画添加动画效果,例如从 display: none
到 display: none
的动画。从 Chrome 116 开始,您可以在关键帧规则中使用 display
和 content-visibility
。您还可以在 50% 点(而非 0% 点)转换任何离散属性。为此,您可以使用 allow-discrete
关键字在 transition-behavior
属性中实现此操作,也可以在 transition
属性中使用此操作作为简写形式。
离散动画抓屏
离散动画演示
详细了解如何转换离散动画。
@starting-style
@starting-style
CSS 规则基于新的 Web 功能,可在 display: none
之间进行动画效果。此规则提供了一种为元素设置“打开前”样式的途径,浏览器可以在元素在页面上打开之前查找此样式。这对于条目动画以及为弹出式窗口或对话框等元素添加动画效果非常有用。当您创建元素并希望为其添加进入动画效果时,此属性也非常有用。下面的示例会将 popover
属性(见下一部分)从视口外部以动画形式平滑地呈现到视图中,并呈现到顶层。
@starting-style 抓屏
@starting-style 演示
详细了解 @starting-style 和其他进入动画。
叠加层
您可以将新的 CSS overlay
属性添加到转场中,以便具有顶层样式的元素(例如 popover
和 dialog
)能够顺畅地从顶层动画化。如果您不对叠加层进行转换,元素将立即恢复剪裁、转换和遮盖状态,并且您不会看到转换过程。同样,overlay
可让 ::backdrop
在添加到顶层元素后平滑地退出动画。
叠加式抓屏
重叠式广告实时演示
详细了解叠加层和其他退出动画。
组件
2023 年是样式和 HTML 组件交叉领域的重要一年,popover
正式发布,我们围绕锚点定位和下拉菜单样式的未来进行了大量工作。借助这些组件,您可以更轻松地构建常见的界面模式,而无需依赖于其他库或每次从头构建自己的状态管理系统。
弹出式窗口
Popover API 可帮助您构建在网页其余部分上方显示的元素。这些内容可能包括菜单、选择和提示。您可以通过向弹出式元素添加 popover
属性和 id
,并使用 popovertarget="my-popover"
将其 id
属性连接到调用按钮,来创建简单的弹出式窗口。Popover API 支持:
- 提升到顶层。弹出式窗口将显示在页面其余部分上方的单独图层中,因此您无需调整 z-index。
- “轻触关闭”功能。点击弹出式窗口区域外部会关闭弹出式窗口并返回焦点。
- 默认焦点管理。打开弹出式窗口后,下一个标签页就会停止在弹出式窗口内。
- 无障碍键盘绑定。按
esc
键或双击即可关闭弹出式窗口并返回焦点。 - 无障碍组件绑定。在语义上将 popover 元素连接到 popover 触发器。
弹出式窗口抓屏
弹出式窗口实时演示
选择中的水平规则
今年,Chrome 和 Safari 中对 HTML 进行了另一项小改,即能够在 <select>
元素中添加水平线元素 (<hr>
标记),以便在视觉上划分内容。以前,将 <hr>
标记放入选择器中根本不会呈现。不过,今年 Safari 和 Chrome 都支持此功能,可更好地分隔 <select>
元素中的内容。
选择屏幕截图
选择“实时演示”
详细了解如何在选择中使用 hr
:用户有效和无效的伪类
:user-valid
和 :user-invalid
今年在所有浏览器中均已稳定运行,其行为与 :valid
和 :invalid
伪类类似,但只有在用户与输入内容进行了显著互动后,才会与表单控件匹配。必填且空的表单控件将与 :invalid
匹配,即使用户尚未开始与网页互动也是如此。在用户更改输入并将其置于无效状态之前,同一控件不会匹配 :user-invalid
。
有了这些新的选择器,就不再需要编写有状态代码来跟踪用户更改的输入。
:user-* 屏幕录制
:user-* 实时演示
详细了解如何使用 user-* 表单验证伪元素。
专属手风琴式折叠
浏览器支持
网站上常见的界面模式是手风琴组件。如需实现此模式,您需要组合几个 <details>
元素,通常会将它们视觉上分组,以表明它们属于同一组。
Chrome 120 中的新功能支持在 <details>
元素中使用 name
属性。使用此属性时,具有相同 name
值的多个 <details>
元素形成语义组。组中最多只能有一个元素处于打开状态:当您打开组中的某个 <details>
元素时,之前打开的那个元素将自动关闭。这种类型的折叠动作条被称为独占折叠动作条。
独占手风琴中的 <details>
元素不一定要是同级元素。它们可以散布在文档中。
过去几年,CSS 经历了一次复兴,尤其是在 2023 年。如果您刚开始接触 CSS,或者只是想复习一下基础知识,请查看我们的免费 Learn CSS 课程以及 web.dev 上提供的其他免费课程。
祝您节日快乐,希望您有机会尽快在工作中融入一些出色的全新 CSS 和界面功能!
Chrome 界面开发者关系团队