CSS 和界面的新变化:2023 年 I/O 大会

过去几个月里,我们迎来了 Web 界面的黄金时代。许多新平台功能已经推出,并在各大浏览器上迅速采用,可以支持比以往更多的 Web 功能和自定义功能。

以下是最近推出或即将推出的 20 项最令人兴奋且影响深远的功能:

新版自适应广告

我们先来了解一些新的自适应设计功能。借助新的平台功能,您可以构建逻辑界面,其中包含拥有自己的自适应样式信息的组件;构建利用系统功能来提供更具原生感的界面的界面;以及通过用户偏好查询让用户参与到设计流程中,实现完全的自定义。

容器查询

Browser Support

  • Chrome: 105.
  • Edge: 105.
  • Firefox: 110.
  • Safari: 16.

Source

容器查询最近在所有现代浏览器中都变得稳定了。它们允许您查询父元素的大小和样式,以确定应将哪些样式应用于其任何子元素。媒体查询只能访问和利用视口中的信息,这意味着它们只能处理网页布局的宏观视图。另一方面,容器查询是一种更精确的工具,可以支持任意数量的布局或布局内的布局。

在以下收件箱示例中,“主要收件箱”和“收藏夹”边栏都是容器。其中的电子邮件会根据可用空间调整网格布局,并显示或隐藏电子邮件时间戳。这是网页中的同一组件,只是显示在不同的视图中

由于我们有容器查询,因此这些组件的样式是动态的。如果您调整页面大小和布局,组件会根据各自分配的空间做出响应。边栏变成了顶部栏,空间更大,布局看起来更像主收件箱。当空间不足时,两者都以精简格式显示。

如需详细了解容器查询和构建逻辑组件,请参阅这篇博文

样式查询

Browser Support

  • Chrome: 111.
  • Edge: 111.
  • Firefox: not supported.
  • Safari: 18.

容器查询规范还允许您查询父容器的样式值。此功能目前已在 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()

Browser Support

  • Chrome: 105.
  • Edge: 105.
  • Firefox: 121.
  • Safari: 15.4.

Source

说到强大的动态功能,:has() 选择器是现代浏览器中新增的最强大的 CSS 功能之一。借助 :has(),您可以通过检查父元素是否包含特定子元素或这些子元素是否处于特定状态来应用样式。这意味着,我们现在实际上拥有了一个父级选择器。

在容器查询示例的基础上,您可以使用 :has() 使组件更具动态性。在其中,具有“星标”元素的项目会应用灰色背景,而具有选中复选框的项目会应用蓝色背景。

演示的屏幕截图

不过,此 API 不仅限于父级选择。您还可以设置父元素中任何子元素的样式。例如,当商品包含星标元素时,标题会以粗体显示。这可通过 .item:has(.star) .title 完成。使用 :has() 选择器,您可以访问父元素、子元素,甚至是同级元素,这使得该 API 非常灵活,每天都会涌现出新的使用情形。

如需了解详情并探索更多演示,请参阅这篇关于 :has()博文

nth-of 语法

Browser Support

  • Chrome: 111.
  • Edge: 111.
  • Firefox: 113.
  • Safari: 9.

Web 平台现在具有更高级的 nth-child 选择功能。高级 nth-child 语法提供了一个新关键字“of”,可让您使用现有的 An+B 微语法,在更具体的子集中进行搜索。

如果您在特殊类上使用常规的 nth-child(例如 :nth-child(2)),浏览器会选择应用了 special 类的第二个子元素。这与 :nth-child(2 of .special) 不同,后者会先预过滤所有 .special 元素,然后从该列表中选择第二个元素。

如需进一步了解此功能,请参阅我们的 nth-of 语法文章

text-wrap: balance

选择器和样式查询并不是我们可以在样式中嵌入逻辑的唯一位置;排版也是一个。从 Chrome 114 开始,您可以使用 text-wrap 属性(值为 balance)为标题实现文本换行平衡。

试用演示版

为了平衡文字,浏览器会有效地执行二分搜索,找到不会导致任何额外行的最小宽度,并在一个 CSS 像素(而非显示像素)处停止。为了进一步减少二分搜索中的步骤,浏览器从平均行宽的 80% 开始。

试用演示版

如需详细了解,请参阅这篇文章

initial-letter

Browser Support

  • Chrome: 110.
  • Edge: 110.
  • Firefox: not supported.
  • Safari: 9.

Source

对网页排版的另一项出色改进是 initial-letter。此 CSS 属性可让您更好地控制嵌入式首字下沉样式。

您可以在 :first-letter 伪元素上使用 initial-letter 来指定:字母的大小(取决于字母所占的行数)。 字母的块偏移量,或字母将位于的“槽”。

如需详细了解如何使用 intial-letter,请点击此处

动态视口单元

Browser Support

  • Chrome: 108.
  • Edge: 108.
  • Firefox: 101.
  • Safari: 15.4.

如今,Web 开发者面临的一个常见问题是,如何实现准确且一致的全视口尺寸调整,尤其是在移动设备上。作为开发者,您希望 100vh(视口高度的 100%)表示“与视口一样高”,但 vh 单位不会考虑移动设备上可收缩的导航栏等因素,因此有时最终高度会过高,导致出现滚动。

显示过多的滚动条

为解决此问题,我们现在在 Web 平台上推出了新的单位值,包括: - 小型视口高度和宽度(或 svhsvw),表示最小的有效视口大小。 - 大视口高度和宽度(lvhlvw),表示最大尺寸。 - 动态视口高度和宽度(dvhdvw)。

当额外的动态浏览器工具栏(例如顶部的地址栏或底部的标签页栏)可见时,动态视口单元的值会发生变化;当这些工具栏不可见时,动态视口单元的值也会发生变化。

可视化呈现新的视口单元

如需详细了解这些新单位,请参阅大型、小型和动态视口单位

广色域色彩空间

Browser Support

  • Chrome: 111.
  • Edge: 111.
  • Firefox: 113.
  • Safari: 15.4.

Source

Web 平台的另一项新增功能是广色域色彩空间。在网络平台上提供广色域颜色之前,您可以拍摄色彩鲜艳的照片,并在新式设备上查看,但无法使按钮、文字颜色或背景与这些鲜艳的颜色值相匹配。

一系列图片在宽色域和窄色域之间过渡,展示了色彩鲜艳度和效果。
亲自尝试一下

不过,现在 Web 平台上新增了一系列颜色空间,包括 REC2020、P3、XYZ、LAB、OKLAB、LCH 和 OKLCH。如需了解新的 Web 色彩空间等内容,请参阅 HD 色彩指南

五个堆叠的三角形,颜色各不相同,用于帮助说明每个新色彩空间的关联和大小。

您可以在开发者工具中立即看到色域的扩展情况,其中白线用于划定 srgb 范围的结束位置以及更广色域的开始位置。

开发者工具显示颜色选择器中的色域线。

还有更多颜色工具可供使用!也不要错过所有出色的渐变改进。Adam Argyle 甚至还构建了一个全新工具,可帮助您试用新的网页颜色选择器和渐变生成器,您可以在 gradient.style 上试用该工具。

color-mix()

Browser Support

  • Chrome: 111.
  • Edge: 111.
  • Firefox: 113.
  • Safari: 16.2.

Source

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);
7 个颜色空间(srgb、linear-srgb、lch、oklch、lab、oklab、xyz),每个颜色空间都显示不同的结果。许多是粉色或紫色,实际上仍为蓝色的很少。
试用演示版

color-mix() 函数提供了一项用户长期以来一直期待的功能:在为不透明颜色值添加一定透明度的同时,保留这些颜色值。现在,您可以使用品牌颜色变量,同时创建不同不透明度的这些颜色变体。实现此目的的方法是将颜色与透明度混合。如果您将品牌颜色蓝色与 10% 透明度混合,则会得到 90% 不透明度的品牌颜色。由此可见,您可以快速构建色彩系统。

您可以在 Chrome 开发者工具中看到此功能的实际效果,样式窗格中会显示一个非常漂亮的预览维恩图图标。

开发者工具屏幕截图,其中显示了维恩图 color-mix 图标

如需查看更多示例和详细信息,请参阅我们关于 color-mix 的博文,或试用此 color-mix() 游乐场

CSS 基础知识

开发能让用户明显受益的新功能是等式的一部分,但 Chrome 中推出的许多功能旨在改善开发者体验,并创建更可靠、更有条理的 CSS 架构。这些功能包括 CSS 嵌套、层叠层、作用域样式、三角函数和单独的转换属性。

嵌套

Browser Support

  • Chrome: 120.
  • Edge: 120.
  • Firefox: 117.
  • Safari: 17.2.

Source

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 嵌套的帖子。

级联层

Browser Support

  • Chrome: 99.
  • Edge: 99.
  • Firefox: 97.
  • Safari: 15.4.

Source

我们发现的另一个开发者痛点是确保样式胜出的情况保持一致,而解决此问题的一部分是更好地控制 CSS 级联。

级联层通过让用户控制哪些层的优先级高于其他层来解决此问题,这意味着可以更精细地控制样式的应用时间。

级联图示

来自 Codepen 项目的屏幕截图
在 Codepen 上探索该项目。

如需详细了解如何使用级联层,请参阅这篇文章

作用域限定的 CSS

Browser Support

  • Chrome: 118.
  • Edge: 118.
  • Firefox: behind a flag.
  • Safari: 17.4.

Source

借助 CSS 作用域样式,开发者可以指定特定样式的适用范围,从而在 CSS 中创建原生命名空间。以前,开发者需要依赖第三方脚本来重命名类,或使用特定的命名惯例来防止样式冲突,但很快,您就可以使用 @scope 了。

在此示例中,我们将 .title 元素的范围限定为 .card。这样可以防止该标题元素与网页上的任何其他 .title 元素(例如博文标题或其他标题)发生冲突。

@scope (.card) {
  .title {
    font-weight: bold;
  }
}

您可以在此实时演示中看到 @scope 和范围限制以及 @layer

演示中的卡片的屏幕截图

如需详细了解 @scope,请参阅 css-cascade-6 规范

三角函数

Browser Support

  • Chrome: 111.
  • Edge: 111.
  • Firefox: 108.
  • Safari: 15.4.

Source

另一项新的 CSS 管道是添加到现有 CSS 数学函数中的三角函数。这些函数在所有现代浏览器中都已稳定,可让您在 Web 平台上创建更自然的布局。一个很好的例子是这个径向菜单布局,现在可以使用 sin()cos() 函数来设计和设置动画效果。

在下面的演示中,圆点围绕中心点旋转。每个点不是围绕自己的中心旋转,然后再向外移动,而是沿 X 轴和 Y 轴平移。X 轴和 Y 轴上的距离是通过分别考虑 --anglecos()sin() 来确定的。

如需详细了解此主题,请参阅我们的三角函数文章

各个转换属性

Browser Support

  • Chrome: 104.
  • Edge: 104.
  • Firefox: 72.
  • Safari: 14.1.

Source

通过各个转换函数,开发者人机工程学不断得到改进。自上次 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 社区群组合作,并确定了三个解决方案作为起点:

  1. 内置弹出式窗口功能,包含事件处理程序、声明式 DOM 结构和无障碍默认设置。
  2. 一种 CSS API,用于将两个元素相互关联,以实现锚定定位。
  3. 一个可自定义的下拉菜单组件,用于在您想要设置选择框内内容的样式时。

弹出式窗口

Popover API 为元素提供了一些很棒的内置浏览器支持功能,例如:

  • 支持顶层,因此您无需管理 z-index。当您打开弹出式窗口或对话框时,您会将相应元素提升到页面顶部的特殊层。
  • auto 弹出式窗口的轻关闭行为免费提供,因此当您在元素外部点击时,弹出式窗口会被关闭、从无障碍功能树中移除,并且焦点会得到妥善管理。
  • Popover 的目标和 popover 本身的结缔组织的默认无障碍功能。

这一切意味着只需编写较少的 JavaScript 就能创建所有这类功能,并跟踪所有这些状态。

弹出式窗口示例

Popover 的 DOM 结构是声明性的,可以像为 popover 元素提供 idpopover 属性一样清晰地编写。然后,将该 ID 同步到将打开弹出式窗口的元素,例如具有 popovertarget 属性的按钮:

<div id="event-popup" popover>
  <!-- Popover content goes in here -–>
</div>

<button popovertarget="event-popup">Create New Event</button>

popoverpopover=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>

离散属性转换

为了让所有这些操作都能顺畅地显示和隐藏弹出式窗口,Web 需要某种方式来为离散属性添加动画效果。这些属性在过去通常无法实现动画效果,例如动画效果从顶层开始和结束,以及从 display: none 开始和结束。

为了让弹出式窗口、选择菜单,甚至对话框或自定义组件等现有元素实现流畅的过渡效果,浏览器正在启用新的管道来支持这些动画。

以下弹出式信息框演示使用 :popover-open(用于打开状态)、@starting-style(用于打开前状态)为弹出式信息框设置动画效果,并直接将转换值应用于元素(用于打开后关闭状态)。为了让所有这些功能都能正常运行,需要将其添加到 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 即将推出,它们与滚动驱动的动画和视图过渡有关

滚动驱动的动画

Browser Support

  • Chrome: 115.
  • Edge: 115.
  • Firefox: behind a flag.
  • Safari: 26.

Source

借助滚动条驱动的动画,您可以根据滚动容器的滚动位置来控制动画的播放。这意味着,当您向上或向下滚动时,动画会向前或向后擦除。此外,借助滚动条驱动的动画,您还可以根据元素在其滚动容器中的位置来控制动画。这样一来,您就可以制作有趣的效果,例如视差背景图片、滚动进度条,以及在进入视图时显示的图片。

此 API 支持一组 JavaScript 类和 CSS 属性,可让您轻松创建声明式滚动条驱动的动画。

如需通过滚动来驱动 CSS 动画,请使用新的 scroll-timelineview-timelineanimation-timeline 属性。 如需驱动 JavaScript Web Animations API,请将 ScrollTimelineViewTimeline 实例作为 timeline 选项传递给 Element.animate()

这些新 API 可与现有的 Web 动画和 CSS 动画 API 协同工作,这意味着它们可以受益于这些 API 的优势。这包括让这些动画在主线程之外运行的功能。没错,您没看错:现在只需添加几行额外的代码,即可实现由滚动驱动的流畅动画,且动画在主线程之外运行。有什么理由不喜欢呢?

如需深入了解如何创建这些由滚动驱动的动画,请参阅这篇关于由滚动驱动的动画的文章

查看过渡

Browser Support

  • Chrome: 111.
  • Edge: 111.
  • Firefox Technology Preview: supported.
  • Safari: 18.

Source

借助 View Transition API,您可以轻松地一步到位地更改 DOM,同时在两种状态之间创建动画过渡效果。这些可以是视图之间的简单淡入淡出,但您也可以控制网页的各个部分应如何过渡。

视图过渡可用作渐进式增强功能:使用任何方法更新 DOM 的代码,并将其封装在视图过渡 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这个精彩的演示中所展示的那样,在视图过渡发生时,其他页面互动(例如播放视频)会继续进行。

View Transitions 目前适用于 Chrome 111 及更高版本的单页应用 (SPA)。我们正在努力实现多页面应用支持。如需了解详情,请参阅我们的完整视图过渡指南,其中会详细介绍相关内容。

总结

请访问 developer.chrome.com,及时了解 CSS 和 HTML 的所有最新动态,并观看 I/O 大会视频,了解更多 Web 平台新功能。