特别声明,本文翻译自@alligatorio的 Control Page Scroll in CSS Using Scroll Snapping一文,受限于译者能力,译文或存在不足,欢迎你们指出。如需转载,烦请注明出处。
滚动捕捉「Scroll Snapping」是一项你确定已经见过的技术。当实现得不佳时,它会十分惹人厌,给用户带来不好的浏览体验。但当实现得好的时候,它又会是用于实现展现内容的功能的好方法,如图片画廊。过去滚动捕捉只能经过JavaScript实现,但如今得益于新的CSS滚动捕捉模块「 CSS Scroll Snap module」,这种效果已经能够经过CSS实现了。
同时使人庆幸的是浏览器能够根据用户的滚动方式自动控制并判断是否利用捕捉点「snap point」捕捉。这能够避免捕捉点阻碍平滑导航这种很差的用户体验。css
让咱们简要介绍一下CSS中的滚动捕捉是如何工做的。html
与CSS grid或者Flexbox的使用相似,滚动捕捉的使用须要定义父级/容器元素,容器内的子元素会根据容器元素上定义的规则进行捕捉。web
Scroll Snapping的相关属性中有一些是应用在容器元素上的,而另外一些则用于子元素。浏览器
容器元素上最重要的属性就是scroll-snap-type
。它令一个普通元素成为一个捕捉容器「snap container」元素,而且经过这个属性能够定义滚动捕捉轴「snap axis」(取值可为:x
,y
,block
,inline
,both
),同时这个属性还能够定义滚动捕捉的严格性「strictness」(取值可为:none
,proximity
,mandatory
).app
假设你想要某个容器在y轴上滚动,而且在任何状况下都进行滚动捕捉,那么你能够这样使用scroll-snap-type
属性:flex
.container { scroll-snap-type: y mandatory; }
若是你想要在两个方向上都进行滚动捕捉,而且捕捉行为也不须要太过严格,那么你能够这样写:google
.container { scroll-snap-type: both proximity; }
另外一个做用于容器元素上的属性是scroll-padding
,它容许为容器设置padding,以免捕捉动做在容器的边缘触发。这个属性的赋值语法与padding属性的语法相同。flexbox
在滚动容器元素的子元素中,scroll-snap-align可能会是最重要的属性。它能够接收如下几个值,none,start,end,center
,以指定元素是在开头、中间、仍是结束时进行滚动捕获。基于滚动轴,并假设当前为从左到右的文本方向,那么start能够是顶部或左侧,而end能够是底部或右侧。翻译
你必需要设置元素的scroll-snap-align属性值,由于它的初始值是none,这表示不会执行任何的捕捉。code
scroll-margin属性的使用方式与margin属性同样,它能够设置元素中的不一样捕捉区域。
scroll-snap-stop属性的取值能够为:normal
和always
,经过这个属性能够指定元素是否强制应用捕捉点,即便用户的滚动行为一般会致使跳过捕捉。这个属性的初始值为normal
。
接下来咱们再也不停留在理论和属性介绍上,来经过一些简单例子的演示一下吧。若是一个元素的滚动是基于y轴之上,且它的scroll strictness
被设置为mandatory
,以下面的代码所示:
<div class="container"> <div>1</div> <div>2</div> <div>3</div> <div>4</div> </div>
.container { scroll-snap-type: y mandatory; overflow-y: scroll; border: 2px solid var(--gs0); border-radius: 8px; height: 33vh; } .container div { scroll-snap-align: start; height: 33vh; display: flex; justify-content: center; align-items: center; font-size: 4rem; } .container div:nth-child(1) { background: hotpink; color: white; } .container div:nth-child(2) { background: azure; } .container div:nth-child(3) { background: blanchedalmond; } .container div:nth-child(4) { background: lightcoral; color: white; }
那么它的效果会像这样:
相反地,将scroll strictness
属性设置为proximity
,那么捕捉行为将只会在snap point
的近距离范围内发生。
.container { /* ... */ scroll-snap-type: y proximity; overflow-y: scroll; } /* ... */
最后,一块儿来看一下当「snap snapping」在两条轴上的滚动条上都产生的时候会是什么样子。图片画廊就是一个这种状况下的完美用例,而咱们这里的容器也刚好是一个网格容器。
首先,写好HTML:
<div class="container2"> <div>1</div> <div>2</div> <div>3</div> <div>4</div> <div>5</div> <div>6</div> <div>7</div> <div>8</div> <div>9</div> </div>
而后是样式:
.container2 { display: grid; grid-template-columns: 100% 100% 100%; scroll-snap-type: both mandatory; overflow: scroll; border: 2px solid var(--gs0); border-radius: 8px; height: 33vh; } .container2 div { scroll-snap-align: start; height: 33vh; display: flex; justify-content: center; align-items: center; font-size: 4rem; } .container2 div:nth-child(1) { background: hotpink; color: white; } .container2 div:nth-child(2) { background: azure; } .container2 div:nth-child(3) { background: blanchedalmond; } .container2 div:nth-child(4) { background: lightcoral; color: white; } .container2 div:nth-child(5) { background: rebeccapurple; color: white; } /* ...你懂得 */
而后实现效果以下:
这篇文章浅显地向你们介绍了一些语法知识,若是你有兴趣了解更多的用例和查看更多示例,下面有几篇不错的文章。