新一代网页样式设置

了解现代 CSS 的一些精彩功能。

目前 CSS 中发生了大量令人兴奋的功能,而当今的浏览器已支持其中许多功能!您可以在下方观看我们在 CDS 2019 大会上的演讲,其中介绍了几项我们认为值得关注的新功能和即将推出的功能。

本博文重点介绍了您目前可以使用的功能,因此请务必观看讲座,更深入地讨论 Houdini 等即将推出的功能。您还可以在 CSS@CDS 页面上找到我们讨论的所有功能的演示。

目录

滚动贴靠

滚动贴靠功能可让您定义当用户垂直和/或水平滚动内容时的贴靠点。它提供内置的滚动惯性和减速功能,并且支持触控。

以下示例代码在 <section> 元素中设置水平滚动,其贴靠点与 <picture> 子元素的左侧对齐:

section {
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scroll-snap-type: x mandatory;
}

section > picture {
  scroll-snap-align: start;
}

具体方法如下:

  • 在父 <section> 元素上:
    • overflow-x 设置为 auto 以允许水平滚动。
    • overscroll-behavior-x 设置为 contain,可防止任何父元素在用户到达 <section> 元素的滚动区域边界时滚动。(贴靠并非绝对必要,但通常是个好主意。)
    • scroll-snap-type 设置为 x(用于水平贴靠)和 mandatory,用于确保视口始终贴靠到最近的贴靠点。
  • 在子级 <picture> 元素中,将 scroll-snap-align 设为起始值,这会在每张照片的左侧设置贴靠点(假设 direction 设为 ltr)。

这里有一个实时演示:

您还可以查看垂直滚动贴靠矩阵滚动贴靠的演示。

:focus-within

:focus-within 解决了一个长期存在的无障碍功能问题:在很多情况下,聚焦子元素会影响父元素的呈现方式,从而使使用辅助技术的用户可以访问界面。

例如,如果您的下拉菜单包含多个项,则当任何项获得焦点时,该菜单应保持可见状态。否则,键盘用户会看不到该菜单。

:focus-within 指示浏览器在焦点位于指定元素的任何子元素时应用样式。回到菜单示例,通过在菜单项上设置 :focus-within,您可以确保菜单项在获得焦点时始终可见:

.menu:focus-within {
  display: block;
  opacity: 1;
  visibility: visible;
}

一张显示聚焦与聚焦在内之间的行为差异的插图。

在下面的演示中,请尝试按 Tab 键在可聚焦元素间切换。您会发现,将鼠标悬停在菜单项上时,相应菜单仍然可见:

媒体查询级别 5

新媒体查询为我们提供了强大的方式,让我们能够根据用户的设备偏好设置调整应用的用户体验。基本上,浏览器会充当系统级偏好设置的代理,我们可以使用媒体查询的 prefers-* 组在 CSS 中响应这些偏好设置:

展示解释系统级用户偏好设置的媒体查询的图表。

以下是我们认为开发者会最感兴趣的新查询:

这些查询对于可访问性而言是巨大的优势。例如,在以前,我们无法知道用户是否已将其操作系统设置为高对比度模式。如果您想为 Web 应用提供一种忠实于您的品牌的高对比度模式,就必须让用户从应用内的界面中进行选择。现在,您可以使用 prefers-contrast 在操作系统中检测高对比度设置。

这些媒体查询的一个令人兴奋的后果是,我们可以针对系统级用户偏好设置的多种组合进行设计,以适应各种用户偏好设置和无障碍功能需求。如果用户想要在光线昏暗的环境中使用高对比度的深色模式,您可以这么做!

对 Adam 来说,“更喜欢减少动作”不会实现为“无动作”很重要。用户声称他们喜欢较少的动作,而不是他们不想播放任何动画。他声称减少运动不等于无运动。以下示例展示了当用户更喜欢减少动作时,使用了淡入淡出动画:

逻辑属性

随着越来越多的开发者开始涉足国际化,逻辑属性解决了一个备受关注的问题。marginpadding 等许多布局属性都假定语言是从上到下、从左到右。

显示传统 CSS 布局属性的示意图。

在设计采用多种语言且具有不同编写模式的网页时,开发者必须针对多个元素分别调整所有属性,这很快就成为了可维护性方面的难题。

通过逻辑属性,您可以在转换和写入模式下保持布局完整性。它们根据内容的语义顺序而不是其空间排列方式动态更新。利用逻辑属性,每个元素都有两个维度:

  • 维度与行中的文本流垂直。(在英语中,block-size 等同于 height。)
  • 内嵌维度与每行文字流平行。(在英语中,inline-size 等同于 width。)

这些维度名称适用于所有逻辑布局属性。因此,例如,在英语中,block-start 等同于 top,而 inline-end 等同于 right

显示新 CSS 逻辑布局属性的示意图。

借助逻辑属性,您只需更改页面的 writing-modedirection 属性即可自动更新其他语言的布局,而无需更新单个元素的数十个布局属性。

通过将 <body> 元素的 writing-mode 属性设置为不同的值,您可以在下面的演示中看到逻辑属性的工作原理:

position: sticky

具有 position: sticky 的元素会保持在块流中,直到它开始离开屏幕,此时它会停止与页面的其余部分滚动,并固定在该元素的 top 值指定的位置。为该元素分配的空间会保留在数据流中,并且当用户向上滚动时,该元素会返回到数据流中。

借助粘性定位,您可以创建许多以前需要 JavaScript 的实用效果。为了展示其中一些可能性,我们制作了多个演示。每个演示版均使用大致相同的 CSS,只是稍微调整了 HTML 标记以创建每种效果。

粘性堆栈

在此演示中,所有粘性元素都共用同一个容器。这意味着,当用户向下滚动时,每个粘性元素都会滑过上一个元素。粘性元素具有相同的卡住位置。

粘性幻灯片

在这里,粘性元素是表亲。(也就是说,它们的父母是兄弟姐妹)。当粘性元素到达其容器的下边界时,它会随容器一起上移,形成一种印象:较低的粘性元素会推高较高的元素。换句话说,它们似乎在争夺卡住位置。

Sticky Desperado

与粘性幻灯片一样,此演示中的粘性元素是同级的。不过,它们已放置在设置为两列网格布局的容器中。

backdrop-filter

借助 backdrop-filter 属性,您可以将图形效果应用到元素后面的区域,而不是应用到元素本身。这可以实现许多很酷的效果,而这在以前只能通过复杂的 CSS 和 JavaScript 技巧来实现,而只需一行 CSS 即可实现。

例如,以下演示使用 backdrop-filter 来实现操作系统样式的模糊处理:

我们已经有一篇关于backdrop-filter的精彩帖子,请前往该网站了解详情。

:is()

虽然 :is() 伪类实际上已经有 10 年的历史了,但它的用处仍然没有达到我们的预期。它接受以逗号分隔的选择器列表作为其参数,并匹配该列表中的任何选择器。这种灵活性使其极其方便快捷,并可显著减少您所提交的 CSS 数量。

一个简单的示例:

button.focus,
button:focus {
  …
}

article > h1,
article > h2,
article > h3,
article > h4,
article > h5,
article > h6 {
  …
}

/* selects the same elements as the code above */
button:is(.focus, :focus) {
  …
}

article > :is(h1,h2,h3,h4,h5,h6) {
  …
}

gap

CSS 网格布局gap(之前为 grid-gap)已经有一段时间了。通过指定所包含元素的内部间距(而非子元素周围的间距),gap 可解决许多常见的布局问题。例如,使用间隙,您不必担心子元素上的外边距导致包含元素的边缘周围多余的空白:

图示:显示 gap 属性如何避免容器元素边缘周围的意外间距。

还有个好消息:gap 即将登陆 Flexbox,它提供与网格相同的间距福利:

  • 只有一个间距声明,而不是多个。
  • 无需为您的项目制定关于哪些子元素应占据间距的惯例,间距由所含元素拥有。
  • 相较于旧策略(例如耳袋鼠),其代码更易于理解。

以下视频展示了为两个元素(一个采用网格布局,另一个采用 flex 布局)使用单个 gap 属性的好处:

目前,在 Flex 布局中只有 FireFox 支持 gap,但不妨观看下面的演示,了解其工作原理:

CSS 胡迪尼

Houdini 是一组适用于浏览器渲染引擎的低阶 API,可让您告知浏览器如何解读自定义 CSS。也就是说,它让您可以访问CSS 对象模型,从而通过 JavaScript扩展CSS。这样做有几个好处:

  • 它为您提供了创建自定义 CSS 功能的更多功能。
  • 可以更轻松地将渲染问题与应用逻辑分离开来。
  • 它比我们目前使用 JavaScript 执行的 CSS polyfill 的性能更高,因为浏览器不再需要解析脚本和执行第二次渲染循环;Houdini 代码将在第一个渲染周期中进行解析。

插图:Houdini 与传统 JavaScript polyfill 的对比情况。

Houdini 是多个 API 的统称。如果您想详细了解这些人及其当前状态,请参阅 Houdini 准备好了吗?在本次讲座中,我们介绍了 Properties 和 Values API、Paint API 以及 Animation Worklet,因为它们目前受支持。我们可以轻松地针对每个激动人心的 API 专门撰写一篇完整的博文,但现在,请查看我们的演讲,简要了解它们以及一些很棒的演示,了解如何利用这些 API 做些什么。

溢出式菜单

还有一些事情尚未发生,我们想再谈谈,但没时间深入探讨,所以我们快速地对它们进行了一轮讨论。⚡ 如果您还没听说过这些功能,别忘了观看演讲的最后一部分

  • size:用于同时设置高度和宽度的属性
  • aspect-ratio:该属性用于为本身没有宽高比的元素设置宽高比
  • min()max()clamp():可用于对任何 CSS 属性(而不仅仅是宽度和高度)设置数字约束的函数
  • list-style-type 是现有属性,但很快将支持更多值,包括表情符号和 SVG
  • display: outer innerdisplay 属性很快将接受两个参数,让您可以明确指定其外部布局和内部布局,而不是使用 inline-flex 等复合关键字。
  • CSS 区域:可让您填充指定的非矩形区域,内容可以进出
  • CSS 模块:JavaScript 将能够请求 CSS 模块,并获取可轻松对其执行操作的丰富对象