新一代 Web 样式

了解现代 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 设置为 start,这会在每个图片的左侧设置捕捉点(假设 direction 设置为 ltr)。

这是一个实时演示

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

:focus-within

:focus-within 解决了长期存在的无障碍功能问题:在许多情况下,聚焦子元素应该影响父元素的呈现,以便 UI 可供辅助技术用户访问。

例如,如果您有一个包含多个项目的下拉菜单,则当任何项目具有焦点时,菜单应保持可见。否则,菜单会为键盘用户消失。

:focus-within 告诉浏览器在指定元素的任何子元素上聚焦时应用样式。回到菜单示例,通过在菜单元素上设置 :focus-within,您可以确保当菜单项具有焦点时,菜单保持可见

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

An illustration showing the difference in behavior between focus and focus-within.

尝试在下面的演示中通过可聚焦元素进行 Tab 键切换。您会注意到,当您聚焦于菜单项时,菜单保持可见

媒体查询级别 5

新的媒体查询为我们提供了强大的方法来根据用户的设备偏好调整我们应用程序的用户体验。基本上,浏览器充当系统级首选项的代理,我们可以在 CSS 中使用 prefers-* 媒体查询组来响应这些首选项

A diagram showing media queries interpreting system-level user preferences.

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

这些查询对于无障碍功能来说是一个巨大的胜利。以前,我们无法知道,例如,用户已将其操作系统设置为高对比度模式。如果您想为 Web 应用程序提供与其品牌保持一致的高对比度模式,则必须要求用户从应用程序内的 UI 中选择它。现在,您可以使用 prefers-contrast 从操作系统检测高对比度设置。

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

对 Adam 来说,重要的是“prefers reduced motion”不会被实现为“no motion”。用户说他们更喜欢减少运动,而不是他们不想要任何动画。他断言减少运动不是没有运动。这是一个示例,当用户喜欢减少运动时,它使用交叉淡入淡出动画

逻辑属性

逻辑属性解决了随着越来越多的开发者处理国际化而变得明显的问题。许多布局属性(如 marginpadding)都假定语言是从上到下、从左到右阅读的。

A diagram showing traditional CSS layout properties.

在为具有不同书写模式的多种语言设计页面时,开发者必须单独调整多个元素的所有这些属性,这很快就会成为维护噩梦。

逻辑属性让您可以跨翻译和书写模式保持布局完整性。它们根据内容的语义顺序而不是其空间排列动态更新。使用逻辑属性,每个元素都有两个维度

  • 维度垂直于行中文本的流向。(在英语中,block-sizeheight 相同。)
  • 内联维度平行于行中文本的流向。(在英语中,inline-sizewidth 相同。)

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

A diagram showing new CSS logical layout properties.

使用逻辑属性,您只需更改页面的 writing-modedirection 属性,而不是更新各个元素上的数十个布局属性,即可自动更新其他语言的布局。

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

position: sticky

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

粘性定位让您可以创建许多以前需要 JavaScript 的有用效果。为了展示一些可能性,我们创建了几个演示。每个演示都主要使用相同的 CSS,并且仅稍微调整 HTML 标记以创建每种效果。

粘性堆叠

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

粘性滑动

在这里,粘性元素是表亲。(也就是说,它们的父元素是兄弟姐妹。)当粘性元素到达其容器的下边界时,它会随容器一起向上移动,从而给人一种较低的粘性元素正在向上推动较高的粘性元素的感觉。换句话说,它们似乎在争夺粘滞位置。

粘性亡命之徒

与粘性滑动类似,此演示中的粘性元素是表亲。但是,它们已被放置在设置为两列网格布局的容器中。

backdrop-filter

backdrop-filter 属性让您可以将图形效果应用于元素后面的区域,而不是元素本身。这使得许多以前只能使用复杂的 CSS 和 JavaScript 黑客技术才能实现的很酷的效果可以通过一行 CSS 完成。

例如,此演示使用 backdrop-filter 来实现 OS 风格的模糊效果

我们已经有一篇关于 backdrop-filter 的精彩文章,因此请前往那里获取更多信息。

:is()

虽然 :is() 伪类实际上已经有十年以上的历史了,但我们认为它仍然没有得到应有的广泛使用。它接受逗号分隔的选择器列表作为其参数,并匹配该列表中的任何选择器。这种灵活性使其非常方便,并且可以显着减少您发布的 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,您不必担心子元素上的外边距会导致包含元素边缘周围出现不需要的空白

Illustration showing how the gap property avoids unintended spacing around edges of a container element.

更好的消息是:gap 即将应用于 flexbox,带来与网格相同的所有间距优势

  • 只有一个间距声明,而不是很多。
  • 无需为您的项目建立关于哪些子元素应该拥有间距的约定——包含元素而是拥有间距。
  • 与旧的策略(如 脑叶切除猫头鹰)相比,代码更容易理解。

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

目前,只有 FireFox 支持 flex 布局中的 gap,但请试用此演示以了解其工作原理

CSS Houdini

Houdini 是一组用于浏览器渲染引擎的底层 API,可让您告诉浏览器如何解释自定义 CSS。换句话说,它使您可以访问 CSS 对象模型,让您可以通过 JavaScript 扩展 CSS。这有几个好处

  • 它为您提供了更强大的功能来创建自定义 CSS 功能。
  • 更容易将渲染问题与应用程序逻辑分离。
  • 它比我们目前使用 JavaScript 进行的 CSS polyfilling 性能更高,因为浏览器将不再需要解析脚本并进行第二次渲染周期;Houdini 代码在第一个渲染周期中解析。

Illustration showing how Houdini works compared to traditional JavaScript polyfills.

Houdini 是 多个 API 的总称。如果您想了解有关它们及其当前状态的更多信息,请查看 Is Houdini Ready Yet?。在我们的演讲中,我们介绍了 Properties and 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 模块并获得一个丰富的对象,该对象易于执行操作