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

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

以下是最近推出或即将推出的 20 项最令人兴奋、最具影响力的功能:

全新自适应广告

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

容器查询

浏览器支持

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

来源

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

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

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

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

样式查询

浏览器支持

  • Chrome:111.
  • Edge:111.
  • Firefox:不受支持。
  • 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()

浏览器支持

  • Chrome:105。
  • 边缘:105。
  • Firefox:121.
  • Safari:15.4。

来源

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

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

演示屏幕截图

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

如需了解详情和浏览更多演示,请参阅这篇博文,了解所有关于“:has()”的内容。

nth-of 语法

浏览器支持

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

网站平台现在提供更高级的第 n 个子项选择功能。高级第 n 个子元素语法提供了一个新关键字(“of”),让您可以使用现有的 An+B 微语法,并在其中搜索更具体的子集。

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

如需详细了解此功能,请参阅介绍“nth-of”语法的文章

text-wrap: balance

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

试用演示

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

试用演示版

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

initial-letter

浏览器支持

  • Chrome:110。
  • Edge:110。
  • Firefox:不受支持。
  • Safari:9.

来源

initial-letter 是 Web 排版的另一项重大改进。借助此 CSS 属性,您可以更好地控制内嵌 Drop Cap 样式。

您可以对 :first-letter 伪元素使用 initial-letter 来指定: 根据字母占据的行数来指定字母的大小。字母的排位偏移量或“接收器”,表示该字母所在的位置。

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

动态视口单元

浏览器支持

  • Chrome:108。
  • 边缘:108。
  • Firefox:101.
  • Safari:15.4。

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

显示的滚动条过多

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

当其他动态浏览器工具栏(例如顶部的地址栏或底部的标签页栏)可见或不可见时,动态视口单位的值会发生变化。

新版视口单元可视化

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

广色域色彩空间

浏览器支持

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

来源

Web 平台的另一项重要新功能是宽色域色彩空间。在 Web 平台上推出宽色域色彩之前,您可以拍摄色彩鲜艳的照片,并在新型设备上查看,但无法让按钮、文本颜色或背景与这些鲜艳的值相匹配。

显示一系列图片在宽色域和窄色域之间转换,说明色彩鲜艳度及其效果。
亲自试用

但现在,我们在 Web 平台上提供了一系列新的颜色空间,包括 REC2020、P3、XYZ、LAB、OKLAB、LCH 和 OKLCH。请参阅高清颜色指南,了解新的网页颜色空间以及更多内容。

五个颜色各异的堆叠三角形,用于帮助说明每种新色彩空间之间的关系和大小。

您可以立即在开发者工具中看到颜色范围的扩展情况,白线界定了 srgb 范围的结束位置以及较广色域颜色范围的起始位置。

在颜色选择器中显示色域线的 DevTools。

还有更多用于颜色的工具!还不要错过我们对渐变效果做出的诸多改进。Adam Argyle 还开发了一款全新工具,可帮助您试用新的 Web 颜色选择器和渐变色构建器,您可前往 gradient.style 试用该工具。

color-mix()

浏览器支持

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

来源

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 开发者工具中查看此功能的运作方式,样式窗格中有一个非常棒的预览 Venn 图标。

显示维恩图颜色混合图标的 DevTools 屏幕截图

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

CSS 基础

构建能够明显提升用户体验的新功能只是其中一部分,但 Chrome 中推出的许多功能旨在改善开发者体验,并打造更可靠、更井然有序的 CSS 架构。这些功能包括 CSS 嵌套、级联层、作用域样式、三角函数和各个转换属性。

嵌套

浏览器支持

  • Chrome:120.
  • 边缘:120。
  • Firefox:117。
  • Safari:17.2.

来源

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 嵌套的文章。

级联层

浏览器支持

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

来源

我们发现的另一个开发者痛点是确保哪种样式优先于其他样式保持一致,而解决此问题的部分方法是更好地控制 CSS 级联。

层级叠加可解决此问题,因为它允许用户控制哪些层的优先级高于其他层,从而更精细地控制样式的应用时间。

级联图示

Codepen Project 的屏幕截图
探索 Codepen 上的项目

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

作用域 CSS

浏览器支持

  • Chrome:118.
  • Edge:118。
  • Firefox:需要切换标志才能使用。
  • Safari:17.4.

来源

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

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

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

您可以在以下实时演示中看到带有作用域限制的 @scope 以及 @layer

演示版中卡片的屏幕截图

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

三角函数

浏览器支持

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

来源

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

在下面的演示中,这些圆点围绕一个中心点旋转。每个点在 X 轴和 Y 轴上平移,而不是绕着每个点的中心向外移动。X 轴和 Y 轴上的距离是分别考虑 --anglecos()sin() 后确定的。

这个 Pen

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

单个转换属性

浏览器支持

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

来源

开发者工效学设计将继续通过单个转换函数改进。自上次举行 I/O 大会以来,单个转换在所有现代浏览器中都稳定。

过去,您需要依赖于 transform 函数来应用子函数来缩放、旋转和平移界面元素。这需要进行大量重复操作,尤其是在动画的不同时间应用多个变换时,更是令人沮丧。

.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 就能创建所有这类功能,并跟踪所有这些状态。

弹出式窗口示例

弹出式窗口的 DOM 结构是声明式的,编写方式与为弹出式窗口元素提供 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,在打开时会获得焦点,并且可以轻松关闭。反之,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 示例,其中有色点对应于日历活动中将显示的颜色,您可以按照以下方式编写该示例:

<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 演示使用 :popover-open 为打开状态、@starting-style 为打开前状态,为打开后关闭状态直接将转换值应用于元素,从而为 popover 创建了进入和退出动画。为了让所有这些都与显示屏配合使用,需要将其添加到 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,可用于实现滚动驱动型动画和视图转换

滚动条驱动的动画

浏览器支持

  • Chrome:115。
  • Edge:115。
  • Firefox:需要切换标志才能使用。
  • Safari:不受支持。

来源

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

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

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

这些新 API 可与现有的 Web Animations API 和 CSS Animations API 搭配使用,这意味着它们可以受益于这些 API 的优势。这包括能够在主线程之外运行这些动画。没错,读对了。现在,您只需再添加几行代码,就能获得由滚动驱动、在主线程之外运行且丝滑流畅的动画。这有什么不好?

如需有关如何创建这些滚动驱动型动画的详尽深入指南,请参阅这篇关于滚动驱动型动画的文章

视图过渡

浏览器支持

  • Chrome:111.
  • Edge:111。
  • Firefox:不受支持。
  • Safari:18.

来源

借助 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这个精彩的演示中所演示的那样,在视图转换期间,其他页面互动(例如正在播放的视频)会继续正常运行。

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

总结

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