过去几个月里,我们迎来了网页界面的黄金时代。新的平台功能已经推出,并在各浏览器之间紧密采用,支持比以往任何时候都更多的 Web 功能和自定义功能。
下面介绍了最近发布或即将推出的 20 项最令人期待且极具影响力的功能:
- 容器查询
- 样式查询
:has()
选择器- nth-of micro 语法
text-wrap: balance
initial-letter
- 动态视口单位
- 广色域色彩空间
color-mix()
- 嵌套
- 级联层
- 作用域样式
- 三角函数
- 个别转换属性
- 弹出式窗口
- 锚点定位
- selectmenu
- 离散属性转换
- 滚动驱动的动画
- 视图过渡
全新的自适应功能
我们先来了解一些新的自适应设计功能。借助新的平台功能,您可以使用拥有自适应样式信息的组件构建逻辑界面,构建能够利用系统功能提供更具原生感的界面的界面,并通过用户偏好查询参与设计流程,以实现完全的可定制性。
容器查询
最近,容器查询在所有现代浏览器中都已稳定。通过它们,您可以查询父元素的尺寸和样式,从而确定应该应用到其任意子元素的样式。媒体查询只能访问和利用视口中的信息,这意味着它们只能处理页面布局的宏视图。另一方面,容器查询是一种更精确的工具,可以支持任意数量的布局或布局内的布局。
在下面的收件箱示例中,主要收件箱和收藏夹边栏都是容器。其中的电子邮件会调整网格布局,并根据可用空间显示或隐藏电子邮件时间戳。这与页面中的组件完全相同,只出现在不同的视图中
由于我们使用的是容器查询,因此这些组件的样式是动态的。如果您调整页面大小和布局,组件会自行分配空间。边栏会变成拥有更多空间的顶栏,而且布局看起来更像主要的收件箱。当空间不足时,这两个图标都会以压缩格式显示。
阅读这篇博文,详细了解容器查询以及如何构建逻辑组件。
样式查询
通过容器查询规范,您还可以查询父级容器的样式值。这目前在 Chrome 111 中已部分实现,您可以在 Chrome 111 中使用 CSS 自定义属性来应用容器样式。
以下示例使用存储在自定义属性值中的天气特征(例如雨、晴和多云)来设置卡片背景和指示器图标的样式。
@container style(--sunny: true) {
.weather-card {
background: linear-gradient(-30deg, yellow, orange);
}
.weather-card:after {
content: url(<data-uri-for-demo-brevity>);
background: gold;
}
}
这只是样式查询的开始。未来,我们将推出布尔值查询,以确定是否存在自定义属性值并减少代码重复;目前,我们还在讨论范围查询,以便根据一系列值应用样式。这样可以使用表示雨天或云层几率的百分比值来应用此处显示的样式。
如需了解详情和查看更多演示,请参阅我们的有关样式查询的博文。
:has()
说到强大的动态功能,:has() 选择器是现代浏览器中最强大的新 CSS 功能之一。借助 :has()
,您可以通过检查父元素是否包含特定子元素或者这些子元素是否处于特定状态来应用样式。也就是说,我们现在基本上就有了父级选择器。
以容器查询示例为基础,您可以使用 :has()
使组件更加动态化。其中包含带“星星”的物品元素应用灰色背景,带有选中复选框的项和蓝色背景。
但此 API 并不局限于父级选择。您还可以设置父项内的任何子项的样式。例如,如果商品包含星标元素,则商品名会显示为粗体。这可通过 .item:has(.star) .title
来实现。使用 :has()
选择器,您可以访问父元素、子元素,甚至同级元素,这使其成为一个非常灵活的 API,每天都在不断出现新的用例。
如需了解详情并浏览更多演示,请参阅这篇博文,了解所有关于“:has()
”的内容。
第 n 个语法
浏览器支持
- 111
- 111
- 113
- 9
Web 平台现在提供更高级的 nth-child 选择。高级 nth-child 语法会提供一个新关键字(“of”),它可让您使用 An+B 的现有微语法,其中包含更具体的子集,供您搜索。
如果您使用常规的 nth-child,例如对特殊类使用 :nth-child(2)
,浏览器将选择已应用特殊类的元素,并且该元素也是第二个子元素。这与 :nth-child(2 of .special)
不同,后者会先预过滤所有 .special
元素,然后从该列表中选择第二个元素。
请参阅关于 nth-of 语法的文章,进一步探索此功能。
text-wrap: balance
选择器和样式查询并不是在样式中嵌入逻辑的唯一途径;排版是另一种。从 Chrome 114 开始,您可以使用值为 balance
的 text-wrap
属性为标题使用文本换行平衡。
为平衡文本,浏览器会对最小宽度有效地执行二进制搜索(不会导致任何额外的行),并以一个 CSS 像素(而不是显示像素)停止。为了进一步减少二进制搜索中的步骤,浏览器从平均线宽的 80% 开始。
如需了解详情,请参阅这篇文章。
initial-letter
另一个对网页排版进行了很好的改进是 initial-letter
。此 CSS 属性可让您更好地控制边衬区下拉上限样式。
您可以对 :first-letter
伪元素使用 initial-letter
来指定:
字母的大小,具体取决于其占的行数。
字母的排位偏移或“接收器”,表示该字母所在的位置。
如需详细了解如何使用 intial-letter
,请点击此处。
动态视口单元
浏览器支持
- 108
- 108
- 101
- 15.4
目前,网络开发者面临的一个常见问题是准确且一致的完整视口尺寸,尤其是在移动设备上。作为开发者,您希望 100vh
(100% 的视口高度)表示“与视口一样高”,但 vh
单元没有考虑到在移动设备上收起导航栏之类的因素,因此有时它会过长导致滚动。
为了解决此问题,我们在网络平台上现在推出了新的单位值,包括:
- 视口高度和宽度较小(或 svh
和 svw
),表示最小的有效视口尺寸。
- 较大的视口高度和宽度(lvh
和 lvw
),表示最大的尺寸。
- 动态视口高度和宽度(dvh
和 dvw
)。
其他动态浏览器工具栏(例如顶部的地址或底部的标签栏)在显示和不显示时,动态视口单元的值会发生变化。
有关这些新广告单元的详细信息,请参阅大、小和动态视口单元。
广色域色彩空间
Web 平台的另一个重要新增功能是广色域颜色空间。在网络平台推出广色域色彩之前,您拍摄的色彩鲜艳的照片可在现代设备上显示,但却无法让按钮、文本颜色或背景与这些鲜明的值相一致。
亲自试用
但现在,我们在 Web 平台上有了一系列新的颜色空间,包括 REC2020、P3、XYZ、LAB、OKLAB、LCH 和 OKLCH。请参阅高清颜色指南,了解新的网页颜色空间和更多内容。
您可以立即在开发者工具中看到颜色范围的扩展情况,白线界定了 srgb 范围的结束位置以及较广色域颜色范围的起始位置。
提供了更多颜色工具!也不容错过梯度方面的所有出色改进。Adam Argyle 甚至还有一款全新的工具可以帮助您尝试新的网页颜色选择器和渐变制作工具,请前往 gradient.style 尝试。
color-mix()
扩展颜色空间是使用 color-mix()
函数。此函数支持混合两种颜色值,以根据混合颜色的通道创建新值。混合的颜色空间会影响结果。在 oklch 等更感知的颜色空间中工作时,应用将经历不同的颜色范围,而不是 srgb 等。
color-mix(in srgb, blue, white);
color-mix(in srgb-linear, blue, white);
color-mix(in lch, blue, white);
color-mix(in oklch, blue, white);
color-mix(in lab, blue, white);
color-mix(in oklab, blue, white);
color-mix(in xyz, blue, white);
<ph type="x-smartling-placeholder">![7 种颜色空间(srgb、Linear-srgb、lch、oklch、lab、oklab、xyz),每个颜色空间显示不同的结果。很多颜色是粉色或紫色的,但实际上仍然是蓝色的。](https://developer.chrome.com/static/blog/whats-new-css-ui-2023/image/7-color-spaces-srgb-lin-b67f50cdf456f.png?hl=zh-cn)
color-mix()
函数提供了一项长期请求的功能:既能保留不透明颜色值,又能为其添加一定透明度。现在,您可以在创建不同不透明度的这些颜色变体时使用品牌颜色变量。方法是混合颜色与透明色。将品牌颜色混合为蓝色与 10% 透明色,即可得到 90% 不透明的品牌颜色。您可以看到,这如何能够帮助您快速构建颜色系统。
现在,您可以在 Chrome 开发者工具中查看此操作的实际效果,“样式”窗格中有一个非常漂亮的预览维恩图图标。
您可以参阅我们关于 color-mix 的博文查看更多示例和详细信息,或者试用此 color-mix() Playground。
CSS 基础知识
构建能够带来明显用户优势的新功能是一个需要考虑的问题,但引入 Chrome 的许多功能的目标是改善开发者体验,以及打造更可靠、更有条理的 CSS 架构。这些功能包括 CSS 嵌套、级联层、作用域样式、三角函数和单独的转换属性。
嵌套
CSS 嵌套是 Sass 广受欢迎的一项功能,也是多年来呼声最高的 CSS 开发者请求之一,现在终于登陆 Web 平台了。嵌套可让开发者以更简洁的分组格式编写代码,减少冗余。
.card {}
.card:hover {}
/* can be done with nesting like */
.card {
&:hover {
}
}
您还可以嵌套媒体查询,这也意味着您可以嵌套容器查询。在以下示例中,如果卡片的容器中有足够的宽度,则卡片会从纵向布局更改为横向布局:
.card {
display: grid;
gap: 1rem;
@container (width >= 480px) {
display: flex;
}
}
当容器具有更多(或等于)480px
的可用内嵌空间时,系统会对 flex
进行布局调整。满足这些条件时,浏览器只会应用新的显示样式。
如需了解详情和查看示例,请参阅我们关于 CSS 嵌套的博文。
级联层
我们发现的另一个开发者痛点是确保样式的一致性优于其他样式,解决这一问题的一个环节是更好地控制 CSS 级联。
级联层可解决此问题,使用户能够控制哪些层的优先级高于其他层,从而更精细地控制何时应用样式。
![Codepen Project 的屏幕截图](https://developer.chrome.com/static/blog/whats-new-css-ui-2023/image/screenshot-codepen-proje-cbc0d46703a16.png?hl=zh-cn)
如需详细了解如何使用级联层,请参阅这篇文章。
作用域 CSS
借助 CSS 作用域样式,开发者可以指定特定样式适用的边界,实质上是在 CSS 中创建原生命名空间。以前,开发者依靠第三方脚本来重命名类,或依靠特定的命名惯例来防止样式冲突,但很快您就可以使用 @scope
。
在本例中,我们将 .title
元素的作用域限定为 .card
。这样可以防止该 title 元素与网页上的任何其他 .title
元素(例如博文标题或其他标题)发生冲突。
@scope (.card) {
.title {
font-weight: bold;
}
}
在此实时演示中,您可以看到带有范围限制的 @scope
以及 @layer
:
详细了解 css-cascade-6 规范中的 @scope
。
三角函数
另一项新的 CSS 处理是添加到现有 CSS 数学函数的三角函数。这些功能现已在所有现代浏览器中都稳定运行,并让您可以在网络平台上创建更自然的布局。这个径向菜单布局就是一个很好的例子,现在,您可以使用 sin()
和 cos()
函数设计其动画并制作动画。
在下面的演示中,这些圆点围绕一个中心点旋转。每个点在 X 轴和 Y 轴上平移,而不是绕着每个点的中心向外移动。X 轴和 Y 轴上的距离是通过分别考虑 --angle
的 cos()
和 sin()
来确定的。
如需详细了解此主题,请参阅我们的三角函数相关文章。
单独的转换属性
开发者工效学设计将继续通过单个转换函数改进。自上次举行 I/O 大会以来,单个转换在所有现代浏览器中都保持稳定。
过去,您需要使用转换函数来应用子函数来缩放、旋转和平移界面元素。这涉及大量重复,并且在动画中的不同时间应用多个转换时尤其令人失望。
.target {
transform: translateX(50%) rotate(30deg) scale(1.2);
}
.target:hover {
transform: translateX(50%) rotate(30deg) scale(2); /* Only scale changed here, yet you have to repeat all other parts */
}
现在,通过分离转换类型并分别应用它们,您可以在 CSS 动画中包含所有这些细节。
.target {
translate: 50% 0;
rotate: 30deg;
scale: 1.2;
}
.target:hover {
scale: 2;
}
这样,在动画播放过程中,平移、旋转或缩放等操作在不同时间里可能会以不同的变化速率同时发生。
如需了解详情,请参阅有关各个转换函数的博文。
可自定义的组件
为了确保通过该 Web 平台满足开发者的一些关键需求,我们与 OpenUI 社区小组合作,确定了三个首先可以采用的解决方案:
- 内置弹出式功能,具有事件处理脚本、声明式 DOM 结构和可访问的默认值。
- 将两个元素相互绑定以实现锚点定位的 CSS API。
- 一种可自定义的下拉菜单组件,适合用于为选定对象中的内容设置样式。
弹出式窗口
Popover API 为元素提供了一些内置的浏览器支持功能,例如:
- 支持顶层,因此您无需管理
z-index
。当您打开弹出式窗口或对话框时,您会将相应元素提升到页面顶部的特殊层。 auto
弹出式窗口中免费的轻关闭行为,因此当您在元素外点击时,弹出式窗口会关闭,从无障碍树中移除,并妥善管理焦点。- 弹出窗口目标的连接组织和弹出窗口本身的默认无障碍功能。
这一切意味着只需编写更少的 JavaScript 就能创建所有此类功能并跟踪所有这些状态。
弹出式窗口的 DOM 结构是声明式的,其编写方式与为弹出式窗口元素指定 id
和 popover
属性一样清晰。然后,将该 ID 同步到将打开弹出式窗口的元素,例如具有 popovertarget
属性的按钮:
<div id="event-popup" popover>
<!-- Popover content goes in here -–>
</div>
<button popovertarget="event-popup">Create New Event</button>
popover
是 popover=auto
的简写形式。值为 popover=auto
的元素在打开时将强制关闭其他弹出式窗口,在打开后获得焦点,并且可以轻易关闭。反之,popover=manual
元素不会强制关闭任何其他元素类型,不会立即获得焦点,也不会轻关闭。他们通过切换开关或其他关闭操作关闭广告。
目前可在 MDN 上找到有关弹出式窗口的最新文档。
锚点定位
弹出式窗口也经常用于对话框和提示等元素,这些元素通常需要锚定于特定元素。以此事件为例。点击日历活动后,系统会在您点击的活动旁边显示一个对话框。日历项是锚点,弹出式窗口是显示活动详情的对话框。
您可以使用 anchor()
函数创建居中的提示,使用锚点的宽度,将提示放置在锚点 x 位置的 50% 处。然后,使用现有的定位值应用其余的展示位置样式。
但是,如果根据您定位的方式决定弹出式窗口不适合视口,该怎么办呢?
为了解决这个问题,Anchor Positioning API 提供了可供自定义的后备位置。以下示例创建了一个名为“top-then-bottom”的后备位置。浏览器会先尝试将提示定位在顶部,如果视口无法容纳,浏览器就会将其定位在底部的锚定元素下。
.center-tooltip {
position-fallback: --top-then-bottom;
translate: -50% 0;
}
@position-fallback --top-then-bottom {
@try {
bottom: calc(anchor(top) + 0.5rem);
left: anchor(center);
}
@try {
top: calc(anchor(bottom) + 0.5rem);
left: anchor(center);
}
}
如需详细了解锚点定位,请参阅此博文。
<selectmenu>
通过弹出窗口和锚点定位,您可以构建完全可自定义的选择菜单。OpenUI 社区小组一直在研究这些菜单的基本结构,并寻求允许自定义其中任何内容的方法。以下面的直观示例为例:
如需构建最左侧的 selectmenu
示例,其中有色点对应于日历活动中将显示的颜色,您可以按照以下方式编写该示例:
<selectmenu>
<button slot="button" behavior="button">
<span>Select event type</span>
<span behavior="selected-value" slot="selected-value"></span>
<span><img src="icon.svg"/></span>
</button>
<option value="meeting">
<figure class="royalblue"></figure>
<p>Meeting</p>
</option>
<option value="break">
<figure class="gold"></figure>
<p>Lunch/Break</p>
</option>
...
</selectmenu>
离散属性转换
为了让所有这些信息都能平稳地过渡出弹出式窗口,网页需要通过某种方式为离散属性添加动画效果。这些是过去通常无法添加动画效果的属性,例如在顶层之间添加动画效果,以及在 display: none
之间添加动画效果。
为了实现对弹出窗口、选择菜单甚至现有元素(例如对话框或自定义组件)的良好过渡,浏览器将启用新的管道来支持这些动画。
以下弹出式窗口演示,针对打开状态使用 :popover-open
,针对打开前状态使用 @starting-style
,为弹出式窗口添加动画效果,并针对“打开后关闭”状态将转换值直接应用于元素。如需让这一切都适用于 display,需要将此属性添加到 transition
属性中,如下所示:
.settings-popover {
&:popover-open {
/* 0. before-change */
@starting-style {
transform: translateY(20px);
opacity: 0;
}
/* 1. open (changed) state */
transform: translateY(0);
opacity: 1;
}
/* 2. After-change state */
transform: translateY(-50px);
opacity: 0;
/* enumarate transitioning properties, including display */
transition: transform 0.5s, opacity 0.5s, display 0.5s allow-discrete;
}
互动次数
介绍到这里,我们来谈谈交互,也就是 Web 界面功能导览的最后一站。
我们已经讨论过为离散属性添加动画效果,但 Chrome 中还出现了一些围绕滚动驱动动画和视图转换而推出的非常令人兴奋的 API。
滚动条驱动的动画
滚动驱动的动画允许您根据滚动容器的滚动位置来控制动画的播放。也就是说,当您向上或向下滚动时,动画会向前或向后拖动。此外,对于滚动驱动的动画,您还可以根据元素在其滚动容器中的位置来控制动画。这样一来,您就可以制作有趣的效果,例如视差背景图片、滚动进度条,以及在进入视图时显示的图片。
此 API 支持一组 JavaScript 类和 CSS 属性,可让您轻松创建声明性滚动驱动型动画。
如需通过滚动来驱动 CSS 动画,请使用新的 scroll-timeline
、view-timeline
和 animation-timeline
属性。
如需驱动 JavaScript Web Animations API,请将 ScrollTimeline
或 ViewTimeline
实例作为 timeline
选项传递给 Element.animate()
这些新 API 可与现有 Web Animations API 和 CSS Animations API 结合使用,这意味着它们能受益于这些 API 的优势。这包括让这些动画在主线程之外运行的功能。没错,读对了。现在,您只需再添加几行代码,就能获得由滚动驱动、在主线程之外运行且丝滑流畅的动画。有什么不好吃的?!
有关如何创建此类滚动驱动动画的详尽指南,请参阅这篇关于滚动驱动动画的文章。
视图过渡
借助 View Transition API,只需一步即可轻松更改 DOM,同时可在两种状态之间创建动画过渡。这些可以是简单的视图之间的淡入淡出,但您也可以控制页面各个部分的转换方式。
视图过渡可以用作渐进式增强功能:将您用于更新 DOM 的代码(通过任意方法更新)封装在 View Transition API 中,为不支持该功能的浏览器提供后备方案。
function spaNavigate(data) {
// Fallback for browsers that don't support this API:
if (!document.startViewTransition) {
updateTheDOMSomehow(data);
return;
}
// With a transition:
document.startViewTransition(() => updateTheDOMSomehow(data));
}
过渡应呈现的外观由 CSS 控制
@keyframes slide-from-right {
from { opacity: 0; transform: translateX(75px); }
}
@keyframes slide-to-left {
to { opacity: 0; transform: translateX(-75px); }
}
::view-transition-old(root) {
animation: 350ms both slide-to-left ease;
}
::view-transition-new(root) {
animation: 350ms both slide-from-right ease;
}
Maxi Ferreira 的这个精彩演示就证明了,其他网页互动(例如播放视频)在视图过渡期间仍在继续。
视图过渡目前适用于 Chrome 111 中的单页应用 (SPA)。正在开发多页应用支持。如需了解详情,请参阅完整的视图转换指南,了解所有相关信息。
总结
访问 developer.chrome.com,及时了解有关 CSS 和 HTML 的所有最新进展,并观看 I/O 视频,了解更多网站着陆方面的信息。