通过声明滚动贴靠位置,打造可控性良好的滚动体验。
CSS 滚动贴靠功能可让 Web 开发者通过声明滚动贴靠位置来打造可控的滚动体验。分页文章和图片轮播界面就是两个常见的例子。CSS 滚动贴靠提供了一个易于使用且一致的 API,用于构建这些热门的用户体验模式。
背景
滚动贴靠的用例
滚动是一种常见且自然的网页内容互动方式。它是平台的原生方式,可让用户访问比屏幕上一次性显示的信息更多的信息,在屏幕空间有限的移动平台上尤为重要。因此,Web 作者越来越倾向于将内容整理成可滚动的平面列表,而不是深层层次结构,这也就不足为奇了。
滚动的主要缺点是缺乏精确度。滚动操作很少会恰好停在段落或句子的开头。如果滚动在页面或图片中间结束,导致内容仅部分可见,那么对于具有有意义边界的分页或分项内容,这种情况会更加明显。这些应用场景受益于可控性良好的滚动体验。
长期以来,Web 开发者一直依赖基于 JavaScript 的解决方案来控制滚动,以帮助解决此缺陷。不过,由于缺乏滚动自定义基元或对合成滚动的访问权限,基于 JavaScript 的解决方案无法提供完全保真的解决方案。CSS 滚动贴靠可确保提供快速、高保真且易于使用的解决方案,该解决方案可在各种浏览器中一致地运行。
CSS 滚动贴靠允许 Web 作者为每个滚动容器标记滚动操作的边界,以便在这些边界处完成滚动操作。然后,浏览器会根据滚动操作的细节、滚动容器的布局和可见性以及贴靠位置的详细信息,选择最合适的结束位置,然后平滑地动画到该位置。回到前面的示例,当用户滚动完轮播界面后,其可见图片会贴靠到位。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="gallery">
<img src="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 属性,可用于调整滚动容器的有效可查看区域或贴靠视口,在计算滚动贴靠对齐方式时会用到。该属性定义了相对于滚动容器内边距框的内边距。在我们的示例中,顶部添加了 15vh 的额外内边距,这会指示浏览器将滚动容器顶部边缘下方 15vh 的较低位置视为滚动贴靠的垂直起始边缘。贴靠时,贴靠目标元素的起始边缘将与此新位置对齐,从而在上方留出空间。
scroll-margin 属性定义了用于调整贴靠目标有效框的起始量,类似于 scroll-padding 在贴靠滚动容器上的运作方式。
您可能已经注意到,这两个属性中没有“snap”一词。这是有意为之,因为它们实际上会修改所有相关滚动操作的框,而不仅仅是滚动贴靠。例如,Chrome 在计算分页滚动操作(例如 PageDown 和 PageUp)的页面大小时,以及在计算 Element.scrollIntoView() 操作的滚动量时,都会考虑这些元素。
与其他滚动 API 的交互
DOM 滚动 API
滚动贴靠会在所有滚动操作(包括由脚本启动的操作)之后发生。当您使用 Element.scrollTo 等 API 时,浏览器会计算操作的预期滚动位置,然后应用适当的贴靠逻辑来找到最终贴靠位置。因此,用户脚本无需为贴靠进行任何手动计算。
流畅滚动
流畅滚动可控制程序化滚动操作的行为,而滚动贴靠可确定其目标位置。由于它们控制的是滚动的不同方面,因此可以结合使用,相辅相成。
滚动回弹行为
滚动回弹行为 API 控制滚动在多个元素之间的链接方式,不受滚动贴靠的影响。
注意事项和最佳实践
当目标元素相距较远时,避免使用强制贴靠。 这可能会导致无法访问贴靠位置之间的内容。
在许多情况下,滚动贴靠可以作为增强功能添加,而无需进行功能检测。
如果需要,请使用 @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()。