原文连接:Practical CSS Scroll Snapping,by Max Kohlercss
CSS 滚动捕捉容许用户完成滚动以后将视口锁定到某个元素的位置。很是适合用来创建下面这样的应用:html
实现滚动捕捉主要依靠两个属性:容器元素的 scroll-snap-type
属性,以及子元素的 scroll-snap-align
属性。最基本的使用方式以下:git
<div class="container">
<section class="child"></section>
<section class="child"></section>
<section class="child"></section>
<p>...</p>
</div>
复制代码
.container {
scroll-snap-type: y mandatory;
}
.child {
scroll-snap-align: start;
}
复制代码
初版中定义的属性与此不一样,是经过 repeat
关键字实现的。github
.container {
/* OLD */
scroll-snap-points-y: repeat(300px);
}
复制代码
这种定义捕捉的方式很局限,只在间距均匀的捕捉点(evenly-spaced snap points)场景下有效,若是个别子元素尺寸与其余的不同,就会有问题。npm
在撰写本文时,Firefox、Internet Explorer 和 Edge 都支持较早版本的规范,而 Chrome(69+)和 Safari 支持较新的基于元素(element-based)的方法。浏览器
你能够同时使用这两种方法(若是布局容许),以便支持这两类浏览器:app
.container {
scroll-snap-type: mandatory;
scroll-snap-points-y: repeat(300px);
scroll-snap-type: y mandatory;
}
.child {
scroll-snap-align: start;
}
复制代码
但我认为使用基于元素的语法才是更灵活的选择,你能够一个下载 polyfill 来支持尚不支持它的浏览器。本文中后续的例子我也都是使用最新的语法写的。ide
注意:工具
不幸的是,polyfill 并无附带浏览器包,若是不使用构建工具的话,使用起来会有点麻烦。我发现一个最简单的方法是连接到 bundle.run 上的脚本,并在加载 DOM 后使用
cssScrollSnapPolyfill()
进行 polyfill 初始化。还须要指出的是,此 polyfill 仅支持基于元素的语法,而不支持repeat
方法。布局
滚动捕捉须要同时设置父元素(容器)属性和子元素属性。这与 Flex 布局和网格布局里概念类型。
下面分别介绍。
mandatory
值表示,在用户中止滚动时,浏览器必须 滚动到一个捕捉点;proximity
属性就没有严格——除非当前滚动的位置合适,不然 不会强制浏览器 滚动到捕捉点。以个人经验,当滚动中止在距离某个捕捉点几百像素内时,捕捉才会发生。
我在工做中发现,mandatory
能提供更一致的用户体验。可是,规范中也指出,在遇到内容元素比滚动容器还高的状况,使用这个值就有点危险。
若是这里的容器元素设置了 scroll-snap-type: mandatory
,它老是会吸附到元素的顶部或下面元素的顶部,使得这个超高元素的中间部份内容是难完整查看。
默认状况下,内容元素会吸附到容器的最边缘。咱们能够经过设置容器的 scroll-padding
属性来作修改。它的语法与 padding
属性同样。
若是布局中出现有可能妨碍内容元素展现的物件(好比,固定标题),使用它就比较有用。
如今再来看看,可在子元素上应用的属性。
经过这个属性,能够指定元素的哪一部分吸附到容器上。可能的取值有三个:start
、center
和 end
。
这些值的含义是相对于滚动方向。若是是垂直滚动,start
指的是元素的顶部边缘。若是你水平滚动,它指的是左边缘。center
和 end
属性值与此同理。属性还支持两个值的语法,分别指定水平和垂直方向上的捕捉对齐方向。
译注:以
scroll-snap-align: start end;
为例,此处第一个值表示垂直滚动时的对齐点,第二个值则表示水平滚动。更多内容,能够参考 MDN 文档。
默认状况下,滚动捕捉只会在用户中止滚动时发生,这表示若是滚动过猛,中间可能会跳过几个捕捉点,而后才会中止。能够经过给子元素设置 scroll-snap-stop: always
来改变这一行为。这会将强制滚动容器在用户继续滚动以前停留在在就近的一个元素上。
在写这篇文章的时候,尚未浏览器原生支持 scroll-snap-stop
属性,尽管 Chrome 有一个 tracking bug 在。
让咱们看一些使用滚动捕捉的例子。
实现垂直吸附滚动只需用到几行 CSS。首先,咱们告诉容器沿其垂直轴捕捉:
.container {
scroll-snap-type: y mandatory;
}
复制代码
而后,定义吸附点(snap points)。这里,咱们指定列表元素的顶部是吸附点:
.child {
scroll-snap-align: start;
}
复制代码
demo:
为了实现水平滑块,咱们告诉容器沿其 x 轴对齐。咱们还使用 scroll-padding
确保子元素在容器中心处对齐。
.container {
scroll-snap-type: x mandatory;
scroll-padding: 50%;
}
复制代码
而后,咱们告诉容器要吸附到哪一个点。为了将图库(gallery)居中,咱们将每一个元素的中心点定为吸附点。
.child {
scroll-snap-align: center;
}
复制代码
demo:
咱们能够直接在 HTML 元素上设置捕捉点:
html { /* body won't work ¯\_(ツ)_/¯ */
scroll-snap-type: y mandatory;
}
复制代码
而后,使每一个部分的大小与视口同样,并将顶部边缘定义为捕捉点:
section {
height: 100vh;
width: 100vw;
scroll-snap-align: start;
}
复制代码
效果(demo):
**这与垂直版本具备相相似,不够捕捉点位于 X 轴上。
body {
scroll-snap-type: x mandatory;
}
section {
height: 100vh;
width: 100vw;
scroll-snap-align: start;
}
复制代码
效果(demo):
滚动捕捉能够同时在两个方向上进行。
.container {
scroll-snap-type: both mandatory;
}
复制代码
而后,咱们将每一个图块的左上角定义为捕捉点:
.tile {
scroll-snap-align: start;
}
复制代码
效果(demo):
基于 CSS 的滚动捕捉的伟大之处在于,你无需直接控制滚动位置。取而代之的是,只需向浏览器提供一个位置列表,系统会自动以适合当前平台的首选项方式作捕捉处理。这表示咱们缩写的滚动捕获效果感受很匹配系统风格(使用了使用相同的动画效果)。
对我来讲,这是 CSS 滚动捕捉优于提供相似功能的 JavaScript 库的主要优点。
根据个人经验,这在移动设备上效果还不错。也许是由于滚动捕捉已是移动平台上本机 UI 的一部分(iOS 和Android 设备上主屏的 App 图表,本质上就是带有捕捉点的水平滑块)。Android 的 Chrome 上的交互特别好,由于它感受像是天然的滚动效果,但视口老是碰巧恰好的地方中止滚动:
在这背后确定有一些梦幻的数学公式使之成为现实。感谢 CSS 滚动捕捉,为咱们免费提供了这么好用的效果。淡然,这种效果也不要滥用在不合适的其余地方,咱们能够把当作一种加强效果是哦也能,好比幻灯片滚动效果这些,彷佛是不错的选择。固然,可能也有其余方面的潜力,我没想到的。
CSS 捕捉点使你可以与浏览器的本机滚动交互挂钩,令界面达到无缝流畅的效果。随着 可能的 JavaScript API 出现,这些功能将变得更增强大。
(正文完)
广告时间(长期有效)
我有一位好朋友开了一间猫舍,在此帮她宣传一下。如今猫舍里养的都是布偶猫。若是你也是个爱猫人士而且有须要的话,不妨扫一扫她的【闲鱼】二维码。不买也没关系,看看也行。
(完)