CSS Scroll-Snap(fullpage.jsの代替)を使用してスクロールセクションをスナップする方法

公開: 2022-07-19

このチュートリアルでは、ユーザーがスクロールすると、あるフルスクリーンセクションから別のセクションにスナップするページを作成します。 この効果は、 fullpage.jsライブラリによって普及しました。 しかし今では、フルページへのライセンスの変更(今はそれを支払う必要があります)、新しいCSSスクロールスナップモジュール、および交差オブザーバーAPIの完全なブラウザーサポートにより、より良いオプションがあります。

したがって、fullpage.jsの代替を探している場合は、ライブラリ全体が必要ない場合もあります。自分でコーディングするだけです。

実際、スナップ効果は100%CSSです。 JSは、画面が「スナップ」して表示されるときに要素をフェードインするために使用されます。

インスピレーションを得るために、CodePenで入手可能なMichelleBarkerによるこの「DinosaurParkスクロールスナップデモ」を利用します。

https://codepen.io/michellebarker/pen/PowYKXJCodePenでMichelleBarker(@michellebarker)によるPenDinosaurParkスクロールスナップデモを参照してください。

「スクロールスナップ」効果を十分に体験するには、これをより大きな画面で表示することをお勧めします。

CSSをIntersectionObserverと組み合わせて使用​​することで、ページの各フルスクリーンセクションをスナップスクロールし、ビューポートに入るときにコンテンツをフェードインします。

さらに良いことに、それはわずか30行のJSコードです! アニメーションはCSSで行われます。 私たちがする必要があるのは、セクションとコンテンツがJSでビューポートに入るタイミングを理解することだけです。

1)ページを作成する

まず、ページを作成するか、この単純な効果と互換性があるように既存のページを構成する必要があります。 ここで注意すべきことが2つあります。

セクションを含む<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>コンテンツ内部</div></ section> <section class = "section section-3"> <header class = "section__header"> <h3class="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 {色:白; 位置:相対; scroll-snap-align:center; 表示:フレックス; フレックス方向:列; 最小-高さ:100vh; } @media(min-height:30em){.section {height:100vh; }}

2)CSSでスナップを構成する

画像-16-11

ここでは、高さが100vhのセクションが複数あることがわかります。

<main>要素も100vhで、overflow-y:scrollがあります。

ユーザーにとって、スクロールの動作はデフォルトのWebページと同じです。

上記のCSSを追加した場合、スナップ効果はすでに機能しています。 それがどのように機能するかを見てみましょう。

まず、「 @media (min-height: 30em) 」クエリは、高さが短いモバイル画面サイズのスナップ効果を無効にします。 メインセクションの下に、スナップを有効にする1つのプロパティがあります。

main {.... scroll-snap-type:y必須; ....}

これは、「スクロールコンテナが存在する場合に、スナップポイントがスクロールコンテナにどの程度厳密に適用されるかを設定する」(MDN)というかっこいい小さなプロパティです。

そして、私たちのセクションの下に、私たちは持っています:

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

このプロパティは、「ボックスのスナップ位置を、スナップコンテナのスナップポート(位置合わせコンテナとして)内のスナップ領域(位置合わせサブジェクトとして)の位置合わせとして指定します」(MDN)。

CSSスクロールスナップモジュールの詳細については、こちらをご覧ください。

そして、それはそれと同じくらい簡単です。 <main>コンテナ(すべてのセクション)内の直接の子は、<main>コンテナの中央にスクロールスナップします。 メインとセクションの両方が100vhであるため、スクロールはセクションからセクションにスナップします。

3)交差点オブザーバーを使用してコンテンツをフェードする

現在、全ページのスクロール効果があります。他に何もしたくない場合は、このセクションをスキップしてWebサイトを楽しむことができます。 ただし、各フルページセクションが表示されたら、その中のコンテンツをフェードインしたいと思います。これは、ユニークでクールな効果です(fullpage.jsでも可能です)。

これを行うには、交差オブザーバーを使用して、<main>ビューポート内のセクションの位置を理解します。

const section = [... document.querySelectorAll( "section")]; let options = {rootMargin: "0px"、threshold: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");}}); }; constobserver = new IntersectionObserver(callback、options); 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);});

ここで行われていることは2つあります。 まず、セクションがビューポートにあることを識別し、セクションが入ると、CSSクラス.is-visibleを追加します。 ビューポートを離れると、そのクラスが削除されます。

さらに、このセクションがビューポートに入ると、連続して(次々に)子要素のそれぞれに250msの遅延のプロパティが設定されます。 これにより、千鳥状のフェードイン効果が得られます。

これは、データコンテンツの属性を持つ要素内の子に対してのみ行われます。 したがって、フェードインを有効にする場合は、ページコンテンツのラッパーに追加する必要があります。

ここで、これを機能させるには、.is-visibleクラスが追加された要素のフェードインアニメーションを設定する必要があります。

@media(min-height: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を参照すると、.section__contentのクラスとdata-content属性を持つコンテンツをラップアラウンドするdivがあることがわかります。

<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>コンテンツ内部</div></ section> <section class = "section section-3"> <header class = "section__header"> <h3class="section__title">探索と発見</h3 > </ header> <div class ="section__content"data-content>内部のコンテンツ</div></ section> </ main>

これにより、JSとCSSが結び付けられます。 ビューポートに入るときに交差オブザーバーによって.is-visibleクラスが追加されるまで、コンテンツの不透明度は0です。 離れると、不透明度0に戻るため、スクロール方向に関係なく、常にフィードが有効になります。

最後に、各子要素に連続して適用されるdelayは、フェードイン効果をずらします。

3番目のセクションに注意してください。 セクションヘッダーはデータコンテンツセクション内にないため、フェードインしません(すでに存在します)。

すべてのコード

デモは次のとおりです。

等方性-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"> <h3class="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 {色:白; 位置:相対; scroll-snap-align:center; 表示:フレックス; フレックス方向:列; 最小-高さ:100vh; } @media(min-height:30em){.section {height:100vh; }} @media(min-height: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; }

JS

const section = [... document.querySelectorAll( "section")]; let options = {rootMargin: "0px"、threshold: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");}}); }; constobserver = new IntersectionObserver(callback、options); 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を使用して、セクションがページに入るタイミングを理解し、千鳥アニメーションを動的に適用しました。 この基本的な例を使用して、最小限のバニラJSとCSSで構築し、いくつかの本当にクールな効果を作成できます。