如何使用 CSS Scroll-Snap 制作捕捉滚动部分(fullpage.js 替代方案)

已发表: 2022-07-19

在本教程中,我们将制作一个页面,当用户滚动时,它会从一个全屏部分捕捉到另一个部分。 这个效果被fullpage.js库推广。 但是现在,由于对 fullpage 的许可更改(您现在需要为此付费)、新的 CSS scroll-snap 模块以及对交叉点观察者 API 的完整浏览器支持,有更好的选择。

因此,如果您正在寻找 fullpage.js 替代方案,您甚至可能不需要整个库,您可以自己编写代码!

事实上,捕捉效果是 100% CSS。 JS 仅用于在屏幕“捕捉”到视图时淡入元素。

我们将利用 CodePen 上 Michelle Barker 的这个“恐龙公园滚动快照演示”来获得灵感:

https://codepen.io/michellebarker/pen/PowYKXJ在 CodePen 上查看 Michelle Barker (@michellebarker) 的 Pen Dinosaur Park 滚动快照演示。

注意,您可能希望在更大的屏幕上查看此内容以充分体验“滚动快照”效果。

通过结合使用 CSS 和 Intersection Observer,我们将使页面的每个全屏部分快速滚动,并在内容进入视口时淡入。

更好的是,它只有大约 30 行 JS 代码! 动画是用 CSS 完成的; 我们需要做的就是了解节和内容何时使用 JS 进入我们的视口。

1)建立你的页面

首先,需要构建一个页面,或者配置一个现有的页面来兼容这个简单的效果。 这里有两点需要注意:

我们正在使用一个<main>元素,其中包含我们的部分。 这个主要元素是 100vh,其中的每个<section>元素也是如此。

HTML:

<main> <section class="section section-1"> <div class="section__content" data-content >里面的内容</div> </section> <section class="section section-2"> <div class= "section__content" data-content >Content inside</div> </section> <section class="section section-3"> <header class="section__header"> <h3 class="section__title">探索和发现</h3 > </header> <div class="section__content" data-content >里面的内容</div> </section> </main>

CSS:

/* 滚动行为 */ @media (min-height: 30em) { main { scroll-snap-type: y 强制; 高度:100vh; 溢出-y:滚动; } } .section { 颜色:白色; 位置:相对; 滚动对齐:居中; 显示:弯曲; 弹性方向:列; 最小高度:100vh; } @media (min-height: 30em) { .section { 高度: 100vh; } }

2) 使用 CSS 配置对齐

图像 16-11

在这里我们可以看到有多个部分,每个部分的高度为 100vh。

<main> 元素也是 100vh,带有overflow-y:scroll。

对于用户而言,滚动行为与默认网页相同。

如果您添加了上面提到的 CSS,则捕捉效果已经在发挥作用。 让我们来看看它是如何工作的。

首先,“ @media (min-height: 30em) ”查询禁用了高度较短的移动屏幕尺寸的捕捉效果。 在主要部分下,有一个属性可以启用捕捉:

main { .... scroll-snap-type: y 强制; ....}

这是一个很酷的小属性“设置在滚动容器上执行快照点的严格程度,以防万一”(MDN)。

然后在我们的部分下,我们有:

.section { .... scroll-snap-align: center; ....}

此属性“属性将框的对齐位置指定为其对齐区域(作为对齐主题)在其对齐容器的对齐端口(作为对齐容器)内的对齐方式”(MDN)。

在此处了解有关 CSS 滚动捕捉模块的更多信息:

就这么简单。 <main> 容器(所有部分)中的直接子级将滚动捕捉到 <main> 容器的中心。 因为 Main 和 Section 都是 100vh,所以滚动将从一个部分到另一个部分。

3) 使用 Intersection Observer 淡化内容

至此,我们已经有了整页滚动效果,如果您不想做任何其他事情,可以跳过此部分并享受您的网站。 但是,当每个整页部分都显示在视图中时,我想淡入其中的内容 - 一种独特而酷炫的效果(也可以通过 fullpage.js 实现)。

为此,我们将使用交叉点观察器来了解部分在 <main> 视口中的位置。

const section = [...document.querySelectorAll("section")]; 让选项= { rootMargin:“0px”,阈值:0.75,}; const callback = (entries, observer) => { entries.forEach((entry) => { const { target } = entry; if (entry.intersectionRatio >= 0.75) { target.classList.add("is-visible") ; } else { target.classList.remove("is-visible"); } }); }; const观察者=新的IntersectionObserver(回调,选项); section.forEach((section, index) => { const sectionChildren = [...section.querySelector("[data-content]").children]; sectionChildren.forEach((el, index) => { el.style .setProperty("--delay", `${index * 250}ms`); });observer.observe(section); });

这里有两件事要做。 首先,它识别一个部分何时在视口中,并在它进入时添加一个 CSS 类.is-visible 。 当它离开视口时,它会删除该类。

此外,当此部分进入视口时,它会连续(一个接一个地)在每个子元素上设置延迟 250 毫秒的属性。 这会产生交错的淡入淡出效果。

它只对具有 data-content 属性的元素中的子元素执行此操作。 因此,如果您想要淡入效果,您需要将其添加到页面内容周围的包装器中。

现在,为了完成这项工作,我们需要为添加了 .is-visible 类的元素设置淡入动画。

@media(最小高度:30em){ .section__content > * { 不透明度:0; 变换: translate3d(0, 4rem, 0); 过渡:不透明度 800ms var(--delay),变换 800ms 三次贝塞尔曲线(0.13, 0.07, 0.26, 0.99) var(--delay); } } .is-visible .section__content > * { 不透明度:1; 变换: translate3d(0, 1rem, 0); } .is-visible .section__img { 不透明度:0.75; }

如果我们从一开始的演示中回顾 HTML,您会看到有一个 div 用 .section__content 类和 data-content 属性围绕内容。

<main> <section class="section section-1"> <div class="section__content" data-content >里面的内容</div> </section> <section class="section section-2"> <div class= "section__content" data-content >Content inside</div> </section> <section class="section section-3"> <header class="section__header"> <h3 class="section__title">探索和发现</h3 > </header> <div class="section__content" data-content >里面的内容</div> </section> </main>

这将我们的 JS 和 CSS 联系在一起。 内容的不透明度为 0,直到.is-visible类在进入视口时由交叉观察者添加。 当它离开时,它会恢复为 0 的不透明度,因此无论您的滚动方向如何,都会有一个有效的提要。

最后,连续应用于每个子元素的delay会错开淡入效果。

注意第三部分。 部分标题不在数据内容部分中,因此它不会淡入(已经存在)。

所有代码

这是演示:

各向同性-2022-07-15-at-15-00-58

这是我们在演示中使用的所有代码:

HTML

<main> <section class="section section-1"> <div class="section__content" data-content> <img class="section__img section__img--left" src="https://s3-us-west-2 .amazonaws.com/s.cdpn.io/85648/trex.svg" alt="T-rex" /> <h2>里面的内容</h2> <p>blah blah blah</p> </div> < /section> <section class="section section-2"> <div class="section__content" data-content> <h2>里面的内容</h2> <p>blah blah blah</p> </div> </ section> <section class="section section-3"> <header class="section__header"> <h3 class="section__title">探索和发现</h3> </header> <div class="section__content" data-content > <h2>里面的内容</h2> <p>blah blah blah</p> </div> </section> </main>

CSS

@media (min-height: 30em) { main { scroll-snap-type: y 强制; 高度:100vh; 溢出-y:滚动; } } .section { 颜色:白色; 位置:相对; 滚动对齐:居中; 显示:弯曲; 弹性方向:列; 最小高度:100vh; } @media (min-height: 30em) { .section { 高度: 100vh; } } @media (min-height: 30em) { .section__content > * { opacity: 0; 变换: translate3d(0, 4rem, 0); 过渡:不透明度 800ms var(--delay),变换 800ms 三次贝塞尔曲线(0.13, 0.07, 0.26, 0.99) var(--delay); } } .is-visible .section__content > * { 不透明度:1; 变换: translate3d(0, 1rem, 0); } .is-visible .section__img { 不透明度:0.75; }

JS

const section = [...document.querySelectorAll("section")]; 让选项= { rootMargin:“0px”,阈值:0.75,}; const callback = (entries, observer) => { entries.forEach((entry) => { const { target } = entry; if (entry.intersectionRatio >= 0.75) { target.classList.add("is-visible") ; } else { target.classList.remove("is-visible"); } }); }; const观察者=新的IntersectionObserver(回调,选项); section.forEach((section, index) => { const sectionChildren = [...section.querySelector("[data-content]").children]; sectionChildren.forEach((el, index) => { el.style .setProperty("--delay", `${index * 250}ms`); });observer.observe(section); });

结论

这是完美的 fullpage.js 替代方案,它不仅仅停留在全屏部分之间的捕捉。 我们还使用交点观察者 API 来了解某个部分何时进入页面,然后动态应用交错动画。 您可以使用这个基本示例来构建并使用最少的 vanilla JS 和 CSS 制作一些非常酷的效果。