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

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

下面列出了最近或即将推出的 20 项最令人兴奋和最具影响力的功能:

全新的自适应功能

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

容器查询

浏览器支持

  • 105
  • 105
  • 110
  • 16

来源

容器查询最近在所有现代浏览器中变得稳定。您可以使用此类查询查询父元素的尺寸和样式,以确定应应用于其任何子元素的样式。媒体查询只能访问和利用来自视口的信息,这意味着它们只能在网页布局的宏视图中运行。另一方面,容器查询是一种更精确的工具,可以在布局中支持任意数量的布局或布局。

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

由于我们使用的是容器查询,因此这些组件的样式是动态的。如果您调整页面大小和布局,组件会对其单独分配的空间作出响应。边栏变成了一个拥有更多空间的顶部栏,布局看起来更像是主要收件箱。如果空间不足,这两种格式就会以精简格式显示。

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

样式查询

浏览器支持

  • 111
  • 111
  • x
  • x

来源

通过容器查询规范,您还可以查询父容器的样式值。目前,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()

浏览器支持

  • 105
  • 105
  • 121
  • 15.4

来源

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

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

演示的屏幕截图

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

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

语法第 n 个

浏览器支持

  • 111
  • 111
  • 113
  • 9

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

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

请参阅关于 nth-of 语法的文章,详细了解此功能。

text-wrap: balance

并不是只有选择器和样式查询可以在样式中嵌入逻辑;排版是另外一种。从 Chrome 114 开始,您可以使用 text-wrap 属性并将值设为 balance,为标题使用文本换行平衡功能。

试用演示

为了平衡文本,浏览器会对最小宽度执行二进制搜索,搜索不会产生多余的行,并在一个 CSS 像素(而非显示像素)处停止。为了进一步减少二进制搜索中的步骤,浏览器从平均线宽的 80% 开始显示。

试用演示

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

initial-letter

浏览器支持

  • 110
  • 110
  • x
  • 9

来源

对网页排版还有一项很好的改进,那就是 initial-letter。此 CSS 属性可让您更好地控制边衬区上限样式。

您可以对 :first-letter 伪元素使用 initial-letter 来指定:字母的大小取决于它所占的行数。字母的区块偏移量或“接收器”。

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

动态视口单元

浏览器支持

  • 108
  • 108
  • 101
  • 15.4

如今,Web 开发者面临的一个常见问题是,完整视口大小调整的准确性和一致性,尤其是在移动设备上。作为开发者,您希望 100vh(视口高度的 100%)表示“与视口一样高”,但 vh 单元没有考虑在移动设备上收回导航栏之类的因素,因此有时这会拉长太长时间并导致滚动。

显示的滚动条过多

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

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

新视口单元可视化

要详细了解这些新的广告单元,请参阅大型、小型和动态视口单元

广色域色彩空间

浏览器支持

  • 111
  • 111
  • 113
  • 15.4

来源

Web 平台新增的另外一个重要新增功能是广色域颜色空间。在网络平台推出广色域色彩之前,您可以拍摄色彩鲜艳的照片,在现代设备上可以查看,但无法获取与这些鲜艳值匹配的按钮、文字颜色或背景。

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

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

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

在开发者工具中,您可以立即看到颜色范围的扩展情况,这条白线表示 srgb 范围的结束位置以及更广色域颜色范围的开始位置。

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

有更多可用于颜色的工具!不要错过任何出色的渐变改进。我们甚至提供了一款全新的工具 Adam Argyle,旨在帮助您试用新的网页颜色选择器和渐变构建器,您可以在 gradient.style 上试用。

color-mix()

浏览器支持

  • 111
  • 111
  • 113
  • 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 DevTools 查看实际效果,以及 styles 窗格中一个非常漂亮的预览维恩图图标。

显示维恩图 color-mix 图标的开发者工具屏幕截图

您可以在我们关于 color-mix 的博文中查看更多示例和详细信息,或试用此 color-mix() playground

CSS 基础

构建能够明显赢得用户的新功能就是要实现的目标之一,但 Chrome 中的许多功能都是以改善开发者体验,以及创建更可靠和更有条理的 CSS 架构为目标。这些功能包括 CSS 嵌套、级联层、作用域样式、三角函数和各个转换属性。

嵌套

浏览器支持

  • 120
  • 120
  • 117
  • 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 嵌套的博文。

级联层

浏览器支持

  • 99
  • 99
  • 97
  • 15.4

来源

我们发现的另一个开发者痛点是,确保一致性是样式优于其他样式的,其中之一是可以更好地控制 CSS 级联。

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

级联图示

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

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

分区 CSS

浏览器支持

  • 118
  • 118
  • x
  • 17.4

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

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

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

您可以在以下现场演示中查看具有范围限制的 @scope@layer

演示卡片的屏幕截图

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

三角函数

浏览器支持

  • 111
  • 111
  • 108
  • 15.4

来源

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

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

有关此主题的更多详细信息,请参阅我们关于三角函数的文章

各个转换属性

浏览器支持

  • 104
  • 104
  • 72
  • 14.1

来源

借助各个转换函数,开发者工效学设计不断得到改进。自我们上次举行 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 弹出式窗口中无任何轻度关闭行为,因此,当您点击元素外部时,弹出式窗口会关闭,从无障碍树中移除,并正确管理焦点。
  • 弹出式窗口目标的关联组织和弹出式窗口本身的默认可访问性。

所有这一切都意味着只需编写较少的 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=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 社区小组一直在研究这些菜单的基本结构,并寻找允许自定义其中任何内容的方法。请参考以下直观示例:

selectmenus 示例

如需构建最左边的 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 添加动画效果。

为实现对弹出式窗口、SelectMenu 甚至现有元素(如对话框或自定义组件)实现完美过渡,浏览器将启用新的管道来支持这些动画。

以下弹出式窗口演示,针对打开状态使用 :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;
}

互动

接下来是互动,这是本单元介绍网页界面功能的最后一站。

我们已经讨论了为离散属性添加动画效果,但在 Chrome 中,还有一些非常精彩的 API 会围绕滚动驱动的动画和视图过渡

滚动条驱动的动画

浏览器支持

  • 115
  • 115
  • x

来源

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

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

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

这些新 API 可与现有的 Web Animations API 和 CSS Animations API 配合使用,这意味着它们将从这些 API 的优势中受益。这包括使这些动画在主线程之外运行的能力。没错,没错,理解得对:现在,只需几行额外的代码,你就可以拥有丝滑的动画,由滚动驱动,在主线程之外运行。不喜欢什么?!

如需查看有关如何制作这些滚动驱动的动画的详尽深入指南,请参阅这篇有关滚动驱动的动画的文章

视图过渡

浏览器支持

  • 111
  • 111
  • x
  • x

来源

利用 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 大会视频,了解更多网站着陆页。