利用位置粘性实现滑动堆叠效果
最近我想实现滚动时卡片堆叠的效果。我找到的最接近的资源是Sanjeev Yadav 的《卡片堆叠:滚动效果》。我想看看是否能仅使用 CSS 实现类似的效果。
基本效果,位置粘性
定位粘性功能可以将元素定位到类似于固定位置,使其相对于父元素保持固定,直到到达父元素的边界。
粘性定位可以看作是相对定位和固定定位的混合体。粘性定位的元素在越过指定的阈值之前,会被视为相对定位;越过阈值之后,它会被视为固定定位,直到到达其父元素的边界。
我们可以使用 position: sticky 将每个幻灯片固定在父级顶部,并设置固定高度。
CSS:
.stacking-slide {
height: 100vh;
width: 100%;
position: sticky;
top: 0;
// Not needed if 100vh
// &:nth-last-child(1) {
// height: 100vh;
// }
}
HTML:
<section class="stacking-slide">
<h2>Section 1</h2>
</section>
<section class="stacking-slide">
<h2>Section 2</h2>
</section>
<section class="stacking-slide">
<h2>Section 3</h2>
</section>
<section class="stacking-slide">
<h2>Section 4</h2>
</section>
<section class="stacking-slide">
<h2>Section 5</h2>
</section>
支持
Position sticky 得到了很好的支持(Can I Use),但如果您需要支持旧版浏览器,可以使用polyfill。
垂直滚动快照
CSS 滚动捕捉功能允许我们在滚动后使每个幻灯片都完美地定位在视口顶部。
CSS Scroll Snap 是 CSS 的一个模块,它引入了滚动捕捉位置,强制滚动容器的滚动端口在滚动操作完成后停止滚动。
为了使用滚动捕捉功能,我们将把各个部分包裹在一个 <div> 元素中.vertical-scroll-snap。该元素的高度固定为 100vh,overflow-y: scroll这样用户就可以在各个部分之间滚动。
接下来,我们将研究滚动捕捉。首先,我们要设置 `scroll-snap` 属性scroll-snap-type(MDN)。该属性定义了滚动时捕捉点的强制执行程度。我们将它设置为 `false` y mandatory。y这表示捕捉位置仅在其垂直轴上生效。mandatory也就是说,如果滚动容器当前未滚动,它将停留在部分的一个捕捉点上。
接下来,我们需要告诉各个部分哪些部分需要与容器对齐。我们将使用scroll-snap-align(CSS技巧)并赋予其值start。
HTML:
<div class="vertical-scroll-snap">
<section class="stacking-slide">
<h2>Section 1</h2>
</section>
<!-- ... -->
</div>
SCSS:
.vertical-scroll-snap {
overflow-y: scroll;
scroll-snap-type: y mandatory;
max-height: 100vh;
}
.stacking-slide {
scroll-snap-align: start;
// ...
}
支持
CSS Scroll snap 有很好的支持(Can I Use),如果需要支持旧版浏览器,可以使用polyfill。
使用 Intersection Observer API 添加一些漂亮的过渡效果。
Intersection Observer API 允许我们检测元素何时进入视口。当元素进入或离开视口时,我们可以触发回调函数。
Intersection Observer API 提供了一种异步观察目标元素与祖先元素或顶级文档视口相交变化的方法。
在以下示例中,.is-intersecting当幻灯片.stacking-slide进入视口 10% 的区域时,我们会添加一个类;当幻灯片离开该区域时,我们会移除该类。现在我们可以使用 CSS 添加一些漂亮的过渡效果。
JS:
const sectionEls = document.querySelectorAll(".stacking-slide");
const options = {
rootMargin: "-10% 0% -10% 0%"
};
const observer = new IntersectionObserver(entries => {
entries.forEach(function(entry) {
if (entry.isIntersecting) {
entry.target.classList.add("is-intersecting");
} else {
entry.target.classList.remove("is-intersecting");
}
});
}, options);
sectionEls.forEach(el => observer.observe(el));
支持
Intersection Observer API 有良好的支持(Can I Use),如果您需要支持旧版浏览器,可以使用polyfill。
感谢阅读,希望您喜欢这篇短文。
文章来源:https://dev.to/vinceumo/slide-stacking-effect-using-position-sticky-91f
