Web 平台因创新而蓬勃发展,CSS 和 Web 界面功能是这一激动人心的演变的最前沿。我们正处于 Web 界面的黄金时代,CSS 新功能以前所未有的速度在各浏览器中发布,为打造美观且富有吸引力的 Web 体验打开了无限可能。 本文将深入探讨 CSS 的现状,探索一些最具变革性意义的新功能,这些功能正在重新定义 Web 应用的构建方式,并将在 2024 年 Google I/O 大会上现场展示。
全新的互动体验
网页体验从根本上讲是您与用户之间的呼叫和响应,因此,投资于优质的用户互动至关重要。我们一直致力于进行一些非常重大的改进,从而解锁前所未有的功能,让用户可在网页内导航和浏览网页。
滚动条驱动的动画
顾名思义,滚动驱动的动画 API 可让您创建基于滚动的动态动画,而无需依赖滚动观察器或其他大量脚本。
创建滚动条驱动的动画
与基于时间的动画在平台上的运作方式类似,您现在可以使用滚动条的滚动进度来启动、暂停和反向动画。因此,当您向前滚动时,您会看到动画播放,而向后滚动时,动画会以相反的方向播放。这样,您就可以创建部分或全页视觉内容,让元素在视口中和视口内进行动画呈现(也称为滚动讲述),从而产生动态视觉冲击力。
滚动驱动型动画可用于突出显示重要内容、引导用户浏览故事,或为网页增添动态效果。
滚动条驱动的动画视觉效果
实时演示
@keyframes appear {
from {
opacity: 0;
scale: 0.8;
}
to {
opacity: 1;
scale: 1;
}
}
img {
animation: appear linear;
animation-timeline: view();
animation-range: entry 25% cover 50%;
}
上述代码通过更改图片的不透明度和缩放比例定义了一个在视口中显示的简单动画。动画由滚动位置驱动。如需创建此效果,请先设置 CSS 动画,然后设置 animation-timeline
。在本例中,带有默认值的 view()
函数会跟踪相对于滚动条(在本例中也称为视口)的图片。
请务必考虑浏览器支持和用户偏好设置,尤其是无障碍功能需求。因此,请使用 @supports
规则检查浏览器是否支持滚动驱动型动画,并将滚动驱动型动画封装在 @media (prefers-reduced-motion: no-preference)
等用户偏好设置查询中,以遵循用户的动作偏好设置。完成这些检查后,您就可以确定您的样式会正常运行,并且动画不会给用户带来问题。
@supports (animation-timeline: view()) {
@media (prefers-reduced-motion: no-preference) {
/* Apply scroll-driven animations here */
}
}
滚动驱动型动画可以指全页滚动式讲述体验,但也可以指更细微的动画,例如在您滚动 Web 应用时,标题栏会最小化并显示阴影。
滚动条驱动的动画视觉效果
实时演示
@keyframes shrink-name {
from {
font-size: 2em;
}
to {
font-size: 1.5em;
}
}
@keyframes add-shadow {
from {
box-shadow: none;
}
to {
box-shadow: 0 4px 2px -2px gray;
}
}
header {
animation: add-shadow linear both;
}
h2 {
animation: shrink-name linear both;
}
header, h2 {
animation-timeline: scroll();
animation-range: 0 150px;
}
此演示使用几种不同的关键帧动画(标题、文本、导航栏和背景),然后对每个动画应用相应的滚动驱动动画。虽然它们各有不同的动画样式,但它们都具有相同的 animation-timeline、最近的滚动条和相同的动画范围(从页面顶部到 150 像素)。
滚动条驱动的动画的性能优势
此内置 API 可减少您需要维护的代码负担,无论是您编写的自定义脚本,还是包含额外的第三方依赖项。它也不需要交付各种滚动观察器,这意味着某些显著的性能优势。这是因为,无论您是直接在 CSS 中使用新 API,还是使用 JavaScript 钩子,滚动驱动型动画在为可在合成器上进行动画处理的属性(例如转换和不透明度)设置动画时,都是在主线程上运行的。
Tokopedia 最近使用滚动条驱动的动画,让产品导航栏在您滚动网页时显示。使用此 API 对代码管理和性能都有很大的好处。
“与使用传统 JS 滚动事件相比,我们成功将代码行数减少了多达 80%,并发现滚动时的平均 CPU 使用率从 50% 降到了 2%。- Andy Wihalim,Tokopedia 高级软件工程师"
滚动效果的未来
我们知道,这些效果将继续让网络变得更加富有吸引力,并且我们已经在考虑下一步该做些什么。这包括不仅能够使用新的动画时间轴,还能够使用滚动点触发动画的开始(称为滚动触发的动画)。
未来,浏览器还将推出更多滚动功能。以下演示展示了这些未来功能的组合。它使用 CSS scroll-start-target
在选择器中设置初始日期和时间,并使用 JavaScript scrollsnapchange
事件更新标题日期,从而轻松地将数据与固定的事件同步。
您也可以在此基础上,使用 JavaScript scrollsnapchanging
事件实时更新选择器。
这些特定功能目前仅在 Canary 中通过标志提供,但它们解锁了之前在平台中无法或非常难以构建的功能,并突出了基于滚动的互动可能性的未来。
如需详细了解如何开始使用滚动驱动型动画,请观看我们团队刚刚推出的新视频系列,该系列视频可在 Chrome for Developers YouTube 频道上找到。在本课程中,您将从 Bramus Van Damme 那里学习滚动驱动型动画的基础知识,包括该功能的运作方式、术语、创建各种效果的方法,以及如何组合效果来打造丰富的体验。这是一个非常棒的视频系列,值得您观看。
视图过渡
我们刚刚介绍了一项用于在网页内呈现动画的强大新功能,但还有一项名为“视图转换”的强大新功能,可用于在网页之间呈现动画,从而打造流畅的用户体验。视图过渡为网页带来了全新的流畅性,让您可以在单个页面(甚至不同页面)之间创建不同视图之间的无缝过渡。
Airbnb 就是其中之一,该公司已经在尝试将视图转换集成到其界面中,以提供流畅无缝的 Web 导航体验。这包括从列出编辑器边栏,到编辑照片和添加设施,所有这些都在一个流畅的用户体验流程中进行。
虽然这些全页效果美观且流畅,但您还可以创建微互动,例如在下例中,列表视图会在用户互动时更新。借助视图转换,您可以轻松实现此效果。
在单页应用中快速启用视图过渡的方法非常简单,只需使用 document.startViewTransition
封装交互,并确保每个过渡元素都有 view-transition-name
、内嵌或使用 JavaScript 动态创建 DOM 节点即可。
演示效果
实时演示
document.querySelectorAll('.delete-btn').forEach(btn => {
btn.addEventListener('click', () => {
document.startViewTransition(() => {
btn.closest('.card').remove();
});
})
});
/* Styles for the transition animation */
::view-transition-old(.card):only-child {
animation: fade-out ease-out 0.5s;
}
查看过渡类
视图转换名称可用于将自定义动画应用于视图转换,但如果有许多元素要进行转换,这种做法可能会很麻烦。今年针对视图转换的首次新更新简化了这个问题,并引入了创建可应用于自定义动画的视图转换类的功能。
浏览器支持
查看过渡类型
视图转换的另一项重大改进是支持视图转换类型。如果您希望在从一个网页视图动画转换到另一个网页视图时使用其他类型的视觉视图转换,则视图转换类型会很有用。
浏览器支持
例如,您可能希望首页以不同于博客页面动画返回到首页的方式以动画形式呈现博客页面。或者,您可能希望页面以不同的方式切换,如以下示例所示,从左到右,反之亦然。之前这样做会比较麻烦。您可以向 DOM 添加类以应用样式,然后必须移除这些类。View-transition-types 使浏览器可以清理旧转换,而无需在启动新转换之前手动清理,从而为您代劳。
您可以在 document.startViewTransition
函数中设置类型,该函数现在接受对象。update
是用于更新 DOM 的回调函数,types
是包含类型的数组。
document.startViewTransition({
update: myUpdate,
types: ['slide', 'forwards']
})
多页面视图转换
Web 之所以强大,是因为它具有极大的扩展性。许多应用不仅仅是单页应用,而是包含多个页面的强大应用。因此,我们非常高兴地宣布,Chromium 126 将为多页应用提供跨文档视图转换支持。
浏览器支持
这一新的跨文档功能集包含同源中的 Web 体验,例如从 web.dev 导航到 web.dev/blog,但不包括跨源导航,例如从 web.dev 导航到 blog.web.dev 或导航到 google.com 等其他网域。
与同一文档视图转换的主要区别之一是,您无需使用 document.startViewTransition()
封装转换。相反,请使用 CSS @view-transition
at-rule 为视图转换涉及的两个页面都选择启用。
@view-transition {
navigation: auto;
}
如需实现更自定义的效果,您可以使用新的 pageswap
或 pagereveal
事件监听器钩入 JavaScript,以便访问视图转换对象。
借助 pageswap
,您可以在获取旧快照之前,在传出网页上进行一些最后一刻的更改;使用 pagereveal
,您可以在新页面初始化后开始渲染之前对其进行自定义。
window.addEventListener('pageswap', async (e) => {
// ...
});
window.addEventListener('pagereveal', async (e) => {
// ...
});
未来,我们计划扩展视图转换功能,包括:
- 受限转换:可将转换限制为 DOM 子树,让页面的其余部分继续保持互动性,并支持同时运行多个视图转换。
- 手势驱动型视图转换:使用拖动或滑动手势触发跨文档视图转换,在 Web 上获得更接近原生体验。
- CSS 中的导航匹配:直接在 CSS 中自定义跨文档视图转换,而不是在 JavaScript 中使用
pageswap
和pagereveal
事件。如需详细了解多页面应用的视图转换,包括如何通过预渲染以最高性能设置这些转换,请观看 Bramus Van Damme 的以下演讲:
支持引擎的界面组件:简化复杂的互动
构建复杂的 Web 应用绝非易事,但 CSS 和 HTML 不断发展完善,使此过程更易于管理。新功能和增强功能简化了界面组件的创建,让您可以专注于打造出色的体验。这项工作是通过 CSS 工作组、Open UI 社区组和 WHATWG(Web 超文本应用技术工作组)等多个关键标准机构和社区组织的协作完成的。
开发者的一个大痛点是,一个看似简单的要求:能够为下拉菜单(选择元素)设置样式。从表面上看,这看起来很简单,但这是一个复杂的问题,涉及平台的许多部分;从布局和渲染,到滚动和互动,再到用户代理样式和 CSS 属性,甚至是对 HTML 本身的更改。
下拉菜单由许多部分组成,并且包含许多必须考虑的状态,例如:
- 键盘绑定(用于进入/退出互动)
- 点击即可关闭
- 活跃的弹出式窗口管理(在一个弹出式窗口打开时关闭其他弹出式窗口)
- 标签页焦点管理
- 直观呈现所选选项值
- 箭头互动样式
- 状态管理(打开/关闭)
目前,您很难自行管理所有这些状态,但平台也无法轻松实现这一点。为了解决此问题,我们将这些部分拆解开来,并推出了一些基本功能,这些功能不仅可以设置下拉菜单的样式,还可以执行更多操作。
Popover API
首先,我们发布了一个名为 popover
的全局属性。我很高兴地宣布,该属性在几周前刚刚达到“新推出的基准”状态。
弹出式窗口元素会使用 display: none
隐藏,直到使用调用程序(例如按钮)或 JavaScript 打开。如需创建基本弹出式窗口,请在元素上设置 popover 属性,并使用 popovertarget
将其 ID 关联到按钮。现在,按钮是调用方,
直观演示
实时演示
<button popovertarget="my-popover">Open Popover</button>
<div id="my-popover" popover>
<p>I am a popover with more information.</p>
</div>
现在,启用 popover 属性后,浏览器无需任何额外的脚本即可处理许多关键行为,包括:
- 提升到顶层。:在网页其余部分之上单独显示的一层,因此您不必操心
z-index
。 - “轻触关闭”功能:点击弹出式窗口区域外部会关闭弹出式窗口并返回焦点。
- 默认标签页焦点管理:打开弹出式窗口后,下一个标签页就会停止在弹出式窗口内。
- 内置键盘绑定。:按
esc
键或切换两次将关闭弹出式窗口并返回焦点。 - 默认组件绑定。:浏览器会将 popover 与其触发器进行语义关联。
您现在可能正在使用此弹出式窗口 API,但可能并未意识到。GitHub 在其首页的“新建”菜单和拉取请求审核概览中实现了弹出式窗口。他们利用 popover polyfill(由 Oddbird 构建),并利用 GitHub 自己的 Keith Cirkel 提供的一些重要支持来逐步增强此功能,以便支持旧版浏览器。
“通过迁移到 popover,我们成功弃用了数千行代码。借助弹出式窗口,我们无需再与神秘的 z 轴数值斗智斗勇... 通过声明式按钮行为建立正确的无障碍树关系,并内置焦点行为,我们的设计系统可以更轻松地以正确的方式实现模式。-GitHub 软件工程师 Keith Cirkel”
为进入和退出效果添加动画
如果设置了弹出式窗口,您可能希望添加一些互动。我们在过去一年内推出了 4 项新的互动功能,以支持为弹出式窗口添加动画效果。其中包括:
能够在关键帧时间轴上为 display
和 content-visibility
添加动画效果。
使用 allow-discrete
关键字的 transition-behavior
属性,用于启用 display
等离散属性的转换。
@starting-style
规则,用于为从 display: none
到顶层的进入效果添加动画效果。
用于控制动画期间顶层行为的叠加层属性。
这些属性适用于您要动画化到顶层的任何元素,无论是弹出式窗口还是对话框。所有这些代码组合起来,带有背景的对话框如下所示:
直观演示
实时演示
dialog, ::backdrop{
opacity: 0;
transition: opacity 1s, display 1s allow-discrete, overlay 1s allow-discrete;
}
[open], [open]::backdrop {
opacity: 1;
}
@starting-style {
[open], [open]::backdrop {
opacity: 0;
}
}
首先,设置 @starting-style
,以便浏览器知道要通过哪种样式将此元素添加到 DOM 中。这同时适用于对话框和背景。然后,为对话框和背景设置打开状态的样式。对于对话框,这使用 open
属性;对于弹出窗口,这则使用 ::popover-open
伪元素。最后,使用 allow-discrete
关键字为 opacity
、display
和 overlay
添加动画,以启用可让离散属性进行转换的动画模式。
锚点定位
弹出式窗口只是故事的开始。一个非常令人兴奋的更新是,Chrome 125 现在支持锚点定位。
使用锚点定位,只需几行代码,浏览器就可以处理将定位元素锚定到一个或多个锚点元素的逻辑。在以下示例中,简单的提示锚定到位于底部中心的每个按钮。
演示效果
实时演示
在 CSS 中设置锚点定位关系,方法是:在锚点元素(在本例中为按钮)上使用 anchor-name
属性,并在定位元素(在本例中为提示)上使用 position-anchor
属性。然后,使用 anchor()
函数应用相对于锚点的绝对或固定定位。以下代码会将提示的顶部放置在按钮的底部。
.anchor {
anchor-name: --my-anchor;
}
.positioned {
position: absolute;
position-anchor: --my-anchor;
}
或者,直接在锚点函数中使用锚点名称,并跳过 position-anchor
属性。当锚定到多个元素时,这非常有用。
.anchor {
anchor-name: --my-anchor;
}
.positioned {
position: absolute;
top: anchor(--my-anchor bottom);
}
最后,为 justify
和 align
属性使用新的 anchor-center
关键字,将定位元素居中对齐到其锚点。
.anchor {
anchor-name: --my-anchor;
}
.positioned {
position: absolute;
top: anchor(--my-anchor bottom);
justify-self: anchor-center;
}
虽然将锚点定位与弹出式窗口搭配使用非常方便,但弹出式窗口绝不是使用锚点定位的必需条件。锚点定位可用于任何两个(或更多)元素,以建立视觉关系。事实上,以下演示的灵感源自 Roman Komarov 的一篇文章,展示了当您将鼠标悬停在列表项上方或按下 Tab 键时,锚定到列表项的下划线样式。
直观演示
实时演示
此示例使用锚点函数,根据 left
、right
和 bottom
的物理属性设置锚点位置。当您将鼠标悬停在其中一个链接上时,目标锚点会发生变化,浏览器会移动目标以应用定位,同时为颜色添加动画效果以产生简洁的效果。
ul::before {
content: "";
position: absolute;
left: anchor(var(--target) left);
right: anchor(var(--target) right);
bottom: anchor(var(--target) bottom);
...
}
li:nth-child(1) { --anchor: --item-1 }
ul:has(:nth-child(1) a:is(:hover, :focus-visible)) {
--target: --item-1;
--color: red;
}
inset-area
定位
除了您可能之前用过的默认定向绝对定位之外,该版本还包含一个新的布局机制,该机制已作为锚点定位 API 的一部分发布,称为内嵌区域。借助内嵌区域,您可以轻松地相对于各自的锚点放置定位元素,并且它适用于 9 个单元格的网格,其中锚定元素位于中心。例如,inset-area: top
会将已定位的元素置于顶部,而 inset-area: bottom
则会将已定位的元素置于底部。
第一个锚点演示的简化版本如下所示,其中使用了 inset-area
:
.anchor {
anchor-name: --my-anchor;
}
.positioned {
position: absolute;
position-anchor: --my-anchor;
inset-area: bottom;
}
您可以将这些位置值与跨度关键字组合使用,以从中心位置开始,向左、向右或全部跨度,占据可用的全部列或行。您还可以使用逻辑属性。为了更轻松地直观了解和掌握这种布局机制,请查看 Chrome 125 及更高版本中的此工具:
由于这些元素已锚定,因此随着锚点的移动,定位元素会在页面中动态移动。因此,在本例中,我们使用的是容器查询样式的卡片元素,这些元素会根据其固有大小调整大小(而您无法使用媒体查询执行此操作),并且随着卡片界面的变化,固定的菜单也会随新布局一起移动。
演示效果
实时演示
使用 position-try-options
实现动态锚点位置
通过结合使用弹出式窗口和锚点定位,您可以更轻松地创建菜单和子菜单导航。此外,当您的锚定元素到达视口边缘时,您也可以让浏览器为您处理定位更改。您可以通过以下几种方式实现此目的。第一种是创建您自己的定位规则。在本例中,子菜单最初位于“店面”按钮的右侧。不过,如果菜单右侧没有足够的空间,您可以创建 @position-try
块,并为其指定自定义标识符 --bottom
。然后,使用 position-try-options
将此 @position-try
代码块连接到锚点。
现在,浏览器会在这些锚定状态之间切换,先尝试右侧位置,然后再切换到底部。这可以通过很好的转场来实现
直观演示
实时演示
#submenu {
position-anchor: --submenu;
top: anchor(top);
left: anchor(right);
margin-left: var(--padding);
position-try-options: --bottom;
transition: top 0.25s, left 0.25s;
width: max-content;
}
@position-try --bottom {
top: anchor(left);
left: anchor(bottom);
margin-left: var(--padding);
}
除了明确的定位逻辑之外,浏览器还提供了一些关键字,供您进行一些基本的互动(例如在块中翻转锚点或内嵌方向)。
position-try-options: flip-block, flip-inline;
如需获得简单的翻转体验,请利用这些翻转关键字值,并完全跳过编写 position-try
定义。现在,只需几行 CSS 代码,您就可以拥有一个功能齐全且可根据位置自适应的锚点定位元素。
演示效果
实时演示
.tooltip {
inset-area: top;
position-try-options: flip-block;
}
详细了解如何使用锚定定位。
分层界面的未来
我们随处可见锚定体验,而本文中介绍的一系列功能非常适合用来释放创意,更好地控制锚定定位的元素和分层界面。但这只是一个开始。例如,目前 popover
仅适用于以按钮作为调用元素,或与 JavaScript 搭配使用。对于维基百科风格的预览(这种模式在 Web 平台上随处可见),用户需要能够与其互动,并且能够通过链接和用户感兴趣的操作触发弹出式窗口,而无需点击,例如悬停或标签页聚焦。
作为 popover API 的后续步骤,我们正在开发 interesttarget
,以满足这些需求,并通过内置的适当无障碍功能钩子,更轻松地重新创建这些体验。这是一个难以解决的无障碍问题,围绕理想行为还有很多悬而未决的问题,但在平台一级解决并规范此功能应该可以改善所有用户的体验。
<a interesttarget="my-tooltip">Hover/Focus to show the tooltip</a>
<span popover=hint id="my-toolip">This is the tooltip</span>
此外,得益于两位第三方开发者 Keith Cirkel 和 Luke Warlow 的工作,我们还提供了另一个面向未来的通用调用方 (invoketarget
),可在 Canary 中进行测试。invoketarget
支持声明式开发者体验,即 popovertarget
提供弹出式窗口,并针对所有互动元素(包括 <dialog>
、<details>
、<video>
、<input type="file">
等)进行了标准化处理。
<button invoketarget="my-dialog">
Open Dialog
</button>
<dialog id="my-dialog">
Hello world!
</dialog>
我们知道,此 API 尚未涵盖某些用例。例如,为将锚定元素连接到其锚点的箭头设置样式(尤其是在锚定元素的位置发生变化时),并让元素能够“滑动”并留在视口中,而不是在到达边界框时捕获到另一个设置的位置。因此,虽然我们很高兴推出这款强大的 API,但也期待未来进一步扩展其功能。
可设置样式的选择器
通过结合使用 popover
和 anchor
,该团队一直在努力,最终实现了可自定义的选择下拉菜单。好消息是,我们已经取得了很大进展。坏消息是,此 API 目前仍处于实验阶段。不过,我很高兴能分享一些实时演示和进展动态,希望能收到您的反馈。
首先,我们在如何让用户选择启用可自定义的新选择体验方面取得了进展。目前,正在为此转换的方法是使用 CSS 中的呈现属性(设置为 appearance: base-select
)。设置外观后,您将选择启用可自定义的新选择体验。
select {
appearance: base-select;
}
除了 appearance: base-select
之外,我们还更新了一些 HTML 内容。这些功能包括能够将选项封装在 datalist
中进行自定义,以及能够在选项中添加图片等任意非交互式内容。您还将可以使用一个新元素 <selectedoption>
,它会将选项的内容反映到自身中,然后您可以根据自己的需求对其进行自定义。此元素非常实用。
演示效果
实时演示
<select>
<button type=popover>
<selectedoption></selectedoption>
</button>
<datalist>
<option value="" hidden>
<p>Select a country</p>
</option>
<option value="andorra">
<img src="Flag_of_Andorra.svg" />
<p>Andorra</p>
</option>
<option value="bolivia">
<img src="Flag_of_Bolivia.svg" />
<p>Bolivia</p>
</option>
...
</datalist>
</select>
以下代码演示了如何在 Gmail 界面中自定义 <selectedoption>
,其中一个视觉图标代表所选的回复类型,以节省空间。您可以在 selectedoption
中使用基本显示样式来区分选项样式和预览样式。在这种情况下,选项中显示的文本可以在 selectedoption
中视觉隐藏。
直观演示
实时演示
selectedoption .text {
display: none;
}
为此 API 重复使用 <select>
元素的最大优势之一是向后兼容性。在此国家/地区选择界面中,您会看到自定义界面,其中包含选项中的国旗图片,以便用户更轻松地解析内容。由于不受支持的浏览器会忽略它们不理解的行,例如自定义按钮、datalist、selectedoption 和选项中的图片,因此回退项将类似于当前的默认选择界面。
自定义选择器可让您发挥无限创意。我特别喜欢这种 Airbnb 风格的国家/地区选择器,因为它采用了自适应设计的巧妙样式。您可以使用即将推出的可样式化选择菜单执行此操作以及更多操作,这对 Web 平台来说是必不可少的补充。
演示效果
实时演示
独家手风琴
解决特定样式(以及随之而来的所有部分)并非 Chrome 团队一直专注的唯一界面组件。第一个额外的组件更新是能够创建独占的折叠式动作条,其中一次只能打开折叠式动作条中的一件内容
浏览器支持
实现此功能的方法是,为多个详情元素应用相同的名称值,从而创建一组关联的详情,就像一组单选按钮一样
<details name="learn-css" open>
<summary>Welcome to Learn CSS!</summary>
</details>
<details name="learn-css">
<summary>Box Model</summary>
<p>...</p>
</details>
<details name="learn-css">
<summary>Selectors</summary>
<p>...</p>
</details>
:user-valid
和:user-invalid
另一项界面组件改进是 :user-valid
和 :user-invalid
伪类。:user-valid
和 :user-invalid
伪类最近在所有浏览器中都已稳定运行,其行为与 :valid
和 :invalid
伪类类似,但只有在用户与输入内容进行了显著互动后,才会与表单控件匹配。这意味着,确定表单值是否已与用户互动或是否已变为“脏值”所需的代码量会大幅减少,这对于提供用户反馈非常有用,并且减少了过去执行此操作所需的大量脚本。
演示版抓屏
实时演示
input:user-valid,
select:user-valid,
textarea:user-valid {
--state-color: green;
--bg: linear-gradient(...);
}
input:user-invalid,
select:user-invalid,
textarea:user-invalid {
--state-color: red;
--bg: linear-gradient(...);
}
详细了解如何使用 user-* 表单验证伪元素。
field-sizing: content
field-sizing: content
是最近推出的另一项实用组件更新,可应用于输入框和文本区域等表单控件。这样,输入的大小就可以根据其内容而增大(或缩小)。field-sizing: content
对文本区域特别有用,因为您不再需要解决固定大小的问题,在输入框过小的情况下,您可能需要向上滚动才能查看在提示的早期部分中输入的内容。
演示版抓屏
实时演示
textarea, select, input {
field-sizing: content;
}
详细了解字段大小调整。
<hr>
(地址:<select>
)
在选择中启用 <hr>
(水平线元素)是另一项小而实用的组件功能。虽然这没有太多的语义用途,但确实可以帮助您很好地区分选定列表中的内容,尤其是您不一定想使用优化组(例如占位值)分组的内容。
选择“屏幕截图”
选择“实时演示”
<select name="majors" id="major-select">
<option value="">Select a major</option>
<hr>
<optgroup label="School of Fine Arts">
<option value="arthist">
Art History
</option>
<option value="finearts">
Fine Arts
</option>
...
</select>
详细了解如何使用“选择时间”选项
改进了生活质量
我们会不断迭代,不仅仅是交互和组件。过去一年,我们还推出了许多其他提升生活质量的更新。
使用预测功能进行嵌套
原生 CSS 嵌套功能已于去年在所有浏览器中推出,并且经过改进以支持先行,这意味着不再要求使用元素名称之前的 &
。这样一来,嵌套就变得更加符合人体工学,并且与我过去习惯的操作方式类似。
我最喜欢 CSS 嵌套的一个方面是,它可以让您直观地分块组件,并在这些组件中包含状态和修饰符,例如容器查询和媒体查询。以前,我习惯在文件底部对所有这些查询进行分组,以便于具体说明。现在,您可以直接在其余代码旁边以合乎逻辑的方式编写这些代码
.card {
/* card base styles */
h2 {
/* child element style */
}
&.highlight {
/* modifier style */
}
&:hover, &:focus {
/* state styles */
}
@container (width >= 300px) {
/* container query styles */
}
}
适用于块布局的 align-content
另一项非常棒的变化是,您可以在块布局中使用 align-content
等居中机制。这意味着,您现在无需应用 flex 或网格布局,即可在 div 中实现垂直居中等操作,并且不会产生您可能不希望从这些布局算法中获得的边际效应(例如防止边距收缩)。
浏览器支持
屏幕截图
实时演示
div {
align-content: center;
}
Text-wrap: balance and pretty
说到布局,随着 text-wrap: balance
和 pretty
的添加,文本布局得到了显著改进。text-wrap: balance
用于更统一的文本块,而 text-wrap: pretty
则侧重于减少文本中最后一行的单例。
演示版抓屏
实时演示
h1 {
text-wrap: balance;
}
详细了解文本换行:余额。
国际排版更新
过去一年,CJK 文本功能的排版布局更新收到了许多实用更新,例如在自然词组边界处换行线的 word-break: auto-phrase
功能。
浏览器支持
以及 text-spacing-trim
,它可以在标点符号之间应用字距调整,以提升中文、日语和韩语排版的可读性,从而提供更赏心悦目的结果。
相对颜色语法
在颜色主题领域,我们对相对颜色语法进行了重大更新。
在此示例中,此处的颜色使用基于 Oklch 的主题设置。随着色相值根据滑块进行调整,整个主题也会随之变化。这可以通过相对颜色语法实现。背景根据色相使用主色,并调整亮度、色度和色相通道以调整其值。--i 是值渐变列表中的同级索引,展示了如何将步进与自定义属性和相对颜色语法相结合来构建主题。
演示版抓屏
实时演示
:root {
--hue: 230;
--primary: oklch(70% .2 var(--hue));
}
li {
--_bg: oklch(from var(--primary)
calc(l - (var(--i) * .05))
calc(c - (var(--i) * .01))
calc(h - (var(--i) + 5)));
}
light-dark()
函数
与 light-dark()
函数一起,主题设置变得更加动态和简化。
light-dark()
函数是一项人体工学改进,可简化颜色主题选项,以便您以更简洁的方式编写主题样式,如 Adam Argyle 在此直观的图表中所示。之前,您需要两个不同的代码块(默认主题和用户偏好设置查询)来设置主题选项。现在,您可以使用 light-dark()
函数在同一行 CSS 中为浅色和深色主题编写这些样式选项。
html {
color-scheme: light dark;
}
button {
background-color: light-dark(lightblue, darkblue);
}
如果用户选择了浅色主题,该按钮将采用浅蓝色背景。 如果用户选择了深色主题,该按钮将采用深蓝色背景。
:has()
选择器
如果不提及过去一年中影响力最大的互操作性亮点之一,我将会遗漏现代界面的重要信息,那就是去年 12 月面向各浏览器推出的 :has()
选择器。此 API 在编写逻辑样式方面具有革命性意义。
借助 :has()
选择器,您可以检查子元素是否具有特定子元素,或者这些子元素是否处于特定状态,并且本质上也可以用作父级选择器。
:has()
已被证明对许多公司(包括 PolicyBazaar)特别有用,这些公司使用 :has()
根据内部内容设置块的样式,例如在比较部分中,如果块中包含要比较的方案,或者块中没有内容,样式就会相应调整。
“借助 :has() 选择器,我们得以省去了基于 JavaScript 对用户所选内容的验证,改用 CSS 解决方案,这种解决方案能够为我们无缝衔接,并提供与之前相同的体验。- Aman Soni,PolicyBazaar 技术主管”
容器查询
现在,新的可用且使用量不断增长的 Web 的另一个重要补充是容器查询,它能够查询元素父项的固有尺寸以应用样式:与仅查询视口大小的媒体查询相比,它更精细。
Angular 最近在 Angular.dev 上创建了一个精美的新文档网站,该网站使用容器查询根据页面上的可用空间设置标题块的样式。因此,即使布局发生变化,从多列边栏布局变为单列布局,标题块也可以自行调整。
如果没有容器查询,则很难实现此类操作,并且需要调整观察器和元素观察器的大小会降低性能。现在,根据父元素的大小设置元素的样式非常简单。
演示版抓屏
实时演示
@property
最后,我们非常高兴地宣布,@property 即将在 Baseline 中推出。这是为 CSS 自定义属性(也称为 CSS 变量)提供语义含义的关键功能,可实现一系列新的互动功能。@property
还支持在 CSS 中使用上下文含义、类型检查、默认值和回退值。为范围式查询等更强大的功能打开大门。这项功能以前是不可能实现的,现在为 CSS 语言提供了如此深度的支持。
演示版抓屏
实时演示
@property --card-bg {
syntax: "<color>";
inherits: false;
initial-value: #c0bae8;
}
总结
随着各种强大的全新界面功能在各种浏览器上不断推出,您将获得无限可能。借助滚动驱动型动画和视图转换,我们可以打造全新的交互体验,让 Web 变得更加流畅且富有互动性,这在以往是不可想象的。有了下一级别的界面组件,您可以比以往更轻松地构建功能强大、自定义美观的组件,而不会破坏完整的原生体验。最后,架构、布局、排版和响应式设计方面的改进不仅能解决一些小问题,还能为开发者提供所需的工具,帮助他们构建适用于各种设备、外形规格和用户需求的复杂界面。
借助这些新功能,您应该能够移除针对性能要求较高的功能(例如滚动讲述)的第三方脚本,并通过锚点定位将元素彼此绑定,构建流畅的页面转换,最终为下拉菜单设置样式,以及以原生方式改进代码的整体结构。
成为一名 Web 开发者的时机从未如此成熟。自 CSS3 宣布以来,网站一直没有带来那么多的活力和激情。过去,我们一直需要但只能想象的功能,如今终于成为现实,并成为了 YouTube 平台的一部分。正是得益于您的支持,我们才能优先开发并最终让这些功能变为现实。我们正在努力让您更轻松地以原生方式完成繁重而乏味的工作,以便您能将更多时间用于构建重要内容,例如让您的品牌脱颖而出的核心功能和设计细节。
如需在这些新功能发布时详细了解它们,请访问 developer.chrome.com 和 web.dev,我们的团队会在这些网站上分享 Web 技术的最新动态。欢迎试用滚动驱动的动画、视图过渡、锚点定位,甚至是样式化选择,并与我们分享您的想法。我们非常乐意倾听您的意见,并随时为您提供帮助。