如何使用 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 製作一些非常酷的效果。