一位客户询问我们是否可以模仿许多移动设备上的 “橡皮筋”滚动行为。我相信你知道我在说什么。这是一种已经存在并且在大多数浏览器中自动发生的。例如,在 iOS Safari 中,您可以将页面滚动到视窗的顶部或底部边缘以外几百像素,然后松开会将页面弹回原位。
我听说过一些情况下,有人 可能想要阻止反弹发生,但没有人要求我实现它,尤其是在支持没有触控界面的设备的方式。实际上,我很惊讶没有现有的 CSS 属性来实现这个功能。虽然有非标准的 -webkit-overflow-scrolling
属性,但它用于不同类型的 “动量”滚动。我也不会想依赖一个尚未纳入规范的非标准属性。
好的,那么如果我们想在工作中强制执行这种橡皮筋效果呢?首先,我们需要某种元素作为需要滚动的内容的容器。当然,我们可以使用 JavaScript,但这涉及添加滚动监听器或 pointerDown
、pointerUp
和 pointerMove
事件的组合,更不用说跟踪位置、惯性运动等等了。
一个仅使用 CSS 的解决方案会更加理想。
这里有一个包含几个子元素的容器
<div class="carousel">
<div class="slides">
<div class="slide">1</div>
<div class="slide">2</div>
<div class="slide">3</div>
<div class="slide">4</div>
<div class="slide">5</div>
</div>
</div>
让我们设置一些基本样式,具体来说是创建一种我们能够保证溢出父容器的情况。
/* Parent container with fixed dimensions for overflow */
.carousel {
width: 200px;
height: 400px;
overflow-x: hidden;
overflow-y: auto;
}
/* Wrapper for slides, stacked in a column */
.slides {
display: flex;
flex-direction: column;
flex-wrap: wrap;
width: 100%;
height: fit-content;
}
/* Each slide is the full width of the carousel */
.slide {
width: 100%;
aspect-ratio: 1;
}
让我们先添加一些垂直边距。如果你的容器只有一个很长的项目,请将其添加到子元素的顶部和底部。如果容器包含多个子元素,你可能需要将 margin
添加到第一个子元素的顶部和最后一个子元素的底部。
.carousel > .slides > .slide:first-child {
margin-top: 100px;
}
.carousel > .slides > .slide:last-child {
margin-bottom: 100px;
}
太好了!现在我们可以滚动到边缘以外,但我们需要一些东西在用户松开手指或指针后将其弹回。为此,我们需要使用 scroll-snap-type
和 scroll-snap-align
属性
.carousel {
scroll-snap-type: y mandatory;
}
.carousel > .slides > .slide {
scroll-snap-align: start;
}
.carousel > .slides > .slide:first-child {
margin-top: 100px;
}
.carousel > .slides > .slide:last-child {
scroll-snap-align: end;
margin-bottom: 100px;
}
请注意,同样适用于水平滚动的元素。为此,你需要将 margin
应用于元素的左右边缘而不是上下边缘。同时,你也需要将 scroll-snap-type
属性的值从 y mandatory
更改为 x mandatory
。
就是这些了!这是最终的演示
我知道,我知道。这并不是什么惊天动地的效果,但这确实解决了一个非常特定的问题。如果你发现自己遇到了这种情况,现在你手里就有可以用的东西了。
其他资源
- “iPhone 标志性‘橡皮筋’效果背后的故事” (Cult of Mac)
- “关于 iOS Safari 橡皮筋滚动的六件事” (Special Agent Squeaky)
- “网站上的滚动反弹” (Smashing Magazine)
并不理想,因为当你处于最后一个元素时,
scroll-margin
会偏移滚动条,让你觉得后面还有更多内容我注意到它在 Firefox 上不起作用
它确实有效,但 Firefox 会停留在滚动区域的开始和结束位置。也就是说,如果你滚动到最顶部,它不会起作用,但如果滚到底部,它就会弹回原位。
嗨,
很有趣
感谢分享