通过声明滚动吸附位置来创建控制良好的滚动体验。
借助 CSS 滚动贴靠功能,Web 开发者可以通过声明滚动贴靠位置来创建可控的滚动体验。分页文章和图片轮播是这方面的两个常见示例。CSS Scroll Snap 提供了一个易于使用且一致的 API,用于构建这些热门的界面设计模式。
背景
滚动吸附的优势
滚动是与网页内容互动的一种常用且自然的方式。它是平台提供对更多信息(而非屏幕上一次性显示的信息)的访问权限的原生方式,在屏幕空间有限的移动平台上尤其重要。因此,Web 作者越来越倾向于将内容整理成可滚动的扁平列表,而不是深层级结构,这一点并不足为奇。
滚动的主要缺点是缺乏精确性。很少有滚动会与段落或句子对齐。如果滚动在网页或图片的中间位置结束,导致部分内容可见,那么对于具有明确边界的分页内容或条目化内容,这种效果会更加明显。这些使用情形可受益于精细控制的滚动体验。
长期以来,Web 开发者一直依赖基于 JavaScript 的解决方案来控制滚动,以帮助解决这一缺点。不过,基于 JavaScript 的解决方案无法提供高保真度的解决方案,因为它们缺少滚动自定义基元或无法访问合成滚动。CSS Scroll Snap 可确保提供快速、高保真且易于使用的解决方案,该解决方案可在各种浏览器中保持一致的运行效果。
CSS Scroll Snap 允许网页作者为每个滚动容器标记边界,以便在滚动操作完成时停止。然后,浏览器会根据滚动操作的细节、滚动容器的布局和可见性以及贴靠位置的详细信息,选择最合适的结束位置,然后平滑地动画到该位置。回到之前的示例,当用户完成轮播界面的滚动操作后,其可见图片会卡入到位。无需 JavaScript 进行滚动调整。
CSS 滚动捕捉
滚动贴靠是指在滚动操作完成后,将滚动容器的滚动偏移调整到首选的贴靠位置。
滚动容器可以使用 scroll-snap-type 属性选择启用滚动吸附。这会告知浏览器,它应考虑将此滚动容器贴靠到其后代产生的贴靠位置。scroll-snap-type 用于确定滚动发生的轴:x、y 或 both,以及贴靠严格程度:mandatory、proximity。稍后会详细介绍这些功能。
通过在元素上声明所需的对齐方式,可以生成贴靠位置。
此位置是指最近的祖先滚动容器和元素在指定轴上对齐时的滚动偏移量。每个轴上可实现以下对齐方式:start、end、center。
start 对齐方式表示滚动容器的吸附点起始边缘应与元素的吸附区域起始边缘对齐。同样,end 和 center 对齐方式表示滚动容器的吸附点结束边缘或中心应与元素吸附区域的结束边缘或中心对齐。
以下示例说明了如何使用这些概念。
示例:横向图库
滚动吸附的常见应用场景是图片轮播界面。例如,如需创建一个横向图片轮播界面,让其在滚动时贴靠到每张图片,我们可以指定滚动容器在横轴上具有强制性 scroll-snap-type。将每张图片设置为 scroll-snap-align: center,以确保贴靠功能可将图片居中放置在轮播界面中。
#gallery {
scroll-snap-type: x mandatory;
overflow-x: scroll;
display: flex;
}
#gallery img {
scroll-snap-align: center;
}
<div id="gal>ler<y"
img src>=&q<uot;cat.jpg">
<img src="dog.jpg"
img> <src=>"another_cute_animal.jpg"
/div
由于贴靠位置与元素相关联,因此贴靠算法可以根据元素和滚动容器的大小,智能地确定何时以及如何进行贴靠。例如,假设有一张图片比轮播界面大。如果采用简单的贴靠算法,可能会导致用户无法平移查看完整图片。但规范要求实现检测到这种情况,并允许用户在该图片中自由滚动,仅在图片边缘进行贴靠。
示例:用户在商品页面上的浏览历程
另一个可从滚动贴靠中受益的常见情况是具有多个逻辑部分(可垂直滚动浏览)的网页,例如典型的产品页面。scroll-snap-type: y proximity; 更适合此类情况。当用户滚动到某个特定部分中间时,它不会进行干扰,但当用户滚动到足够近时,它会进行贴靠并将注意力吸引到新部分。
具体方法如下:
article {
scroll-snap-type: y proximity;
/* Reserve space for header plus some extra space for sneak peeking. */
scroll-padding-top: 15vh;
overflow-y: scroll;
}
section {
/* Snap align start. */
scroll-snap-align: start;
}
header {
position: fixed;
height: 10vh;
}
<article>
<header> Header </header>
<section> Section One </section>
<section> Section Two </section>
<section> Section Three </section>
</article>
滚动内边距和外边距
商品页面具有固定位置的顶部页眉。该设计还要求在滚动容器贴靠时,顶部部分应保持可见,以便为用户提供有关上方内容的提示。
scroll-padding 属性是一种新的 CSS 属性,可用于调整滚动容器(或 snapport)的有效可视区域,该区域在计算滚动吸附对齐方式时使用。该属性定义了相对于滚动容器内边距框的边衬区。在我们的示例中,顶部添加了 15vh 的额外内边距,这会指示浏览器将滚动容器顶部边缘下方 15vh 的位置视为滚动吸附的垂直起始边缘。在贴靠时,贴靠目标元素的起始边缘将与此新位置对齐,从而在上方留出空间。
scroll-margin 属性用于定义外边距量,以调整贴靠目标有效框,类似于 scroll-padding 函数在贴靠滚动容器上的作用。
您可能已经注意到,这两个属性中没有“snap”字样。这是有意为之,因为它们实际上会针对所有相关的滚动操作修改盒子,而不仅仅是滚动贴靠。例如,在计算分页滚动操作(如 PageDown 和 PageUp)的网页大小时,以及在计算 Element.scrollIntoView() 操作的滚动量时,Chrome 会将它们考虑在内。
与其他滚动 API 的互动
DOM 滚动 API
滚动吸附发生在所有滚动操作(包括由脚本发起的滚动操作)之后。当您使用 Element.scrollTo 等 API 时,浏览器会计算操作的预期滚动位置,然后应用适当的贴靠逻辑来查找最终贴靠位置。因此,用户脚本无需进行任何手动计算即可实现贴靠。
流畅滚动
平滑滚动控制程序化滚动操作的行为,而滚动贴靠则决定其目的地。由于它们控制的是滚动操作的正交方面,因此可以一起使用,并且可以相互补充。
滚动回弹行为
过滚动行为 API 用于控制滚动在多个元素之间的链接方式,不受滚动贴靠的影响。
注意事项和最佳实践
当目标元素间距较大时,请避免使用强制对齐。 这可能会导致 snap 位置之间的内容无法访问。
在许多情况下,无需进行功能检测,即可添加滚动吸附功能作为增强功能。
如果需要,请使用 @supports 或 CSS.supports 检测对 CSS 滚动捕捉的支持情况。
避免使用已弃用的规范中也存在的 scroll-snap-type。
CSS 中的功能检测
@supports (scroll-snap-align: start) {
article {
scroll-snap-type: y proximity;
scroll-padding-top: 15vh;
overflow-y: scroll;
}
}
JavaScript 中的功能检测
if (CSS.supports('scroll-snap-align: start')) {
// use css scroll snap
} else {
// use fallback
}
请勿假设以编程方式滚动的 API(例如 Element.scrollTo)始终在请求的滚动偏移处完成。滚动吸附可能会在程序化滚动完成后调整滚动偏移量。请注意,即使在滚动吸附之前,这种假设也并不合理,因为滚动可能会因其他原因而中断,但在使用滚动吸附时,这种情况尤为明显。
未来的工作
Chrome 团队最近进行的一项调查重点关注了滚动体验。
调查结果显示,需要进一步努力才能缩小插件库与 CSS 之间的差距。我们即将开展的工作将侧重于 scroll-snap,包括:
- 各浏览器中的 API 可用性和兼容性。
- 开发新的 CSS API,例如
scroll-start。 - 处理新的 JS 事件,例如
snapChanged()。