在本教程中,我們將製作一個頁面,當用戶滾動時,它會從一個全屏部分捕捉到另一個部分。 這個效果被fullpage.js
庫推廣。 但是現在,由於對 fullpage 的許可更改(您現在需要為此付費)、新的 CSS scroll-snap 模塊以及對交叉點觀察者 API 的完整瀏覽器支持,有更好的選擇。
因此,如果您正在尋找 fullpage.js 替代方案,您甚至可能不需要整個庫,您可以自己編寫代碼!
事實上,捕捉效果是 100% CSS。 JS 僅用於在屏幕“捕捉”到視圖時淡入元素。
我們將利用 CodePen 上 Michelle Barker 的這個“恐龍公園滾動快照演示”來獲得靈感:
通過結合使用 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 配置對齊
在這裡我們可以看到有多個部分,每個部分的高度為 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
會錯開淡入效果。
注意第三部分。 部分標題不在數據內容部分中,因此它不會淡入(已經存在)。
所有代碼
這是演示:
這是我們在演示中使用的所有代碼:
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 製作一些非常酷的效果。