スムーススクロール実装の令和版ベストプラクティス

2023年2月15日 WEB制作 , ,

スムーススクロールとは?

ページ内アンカーリンクなどをクリックまたはタップした際、指定した要素まで滑らかな動きでスクロールさせるテクニックのことを一般的に「スムーススクロール」と呼びます。

WEBサイトでスムーススクロールを実装する場合は、これまでjavascriptを使うケースが多かったと思いますが、IEのサポートが終了した2022年以降からCSSのみでも実装が可能になりました。

scroll-behavior: smooth

CSSプロパティscroll-behavior: smoothをhtml要素に定義すると、ページのすべてのスクロールが滑らかなスクロールになります。

html要素以外に定義してもスムーススクロールにならないので注意が必要です。

デモを作成したので実際に触ってみるとわかりやすいと思います。

デモページを別タブで見る

スムーススクロールの実装方法

html要素にscroll-behavior: smoothを定義するだけです。

CSS

html {
    scroll-behavior: smooth;
}

スクロールのターゲットとする要素にid属性を追加し、それに対応するアンカーリンクのhref属性には「# + id名」と設定します。

HTML

<header>
    <div id="nav">
      <a href="#りんご">りんご</a>
      <a href="#ごりら">ごりら</a>
      <a href="#らっぱ">らっぱ</a>
    </div>
</header>

<main>
    
    <section>
        <h2 id="りんご">りんご</h2>
      
    </section>
    <section>
        <h2 id="ごりら">ごりら</h2>
      
    </section>
    <section>
        <h2 id="らっぱ">らっぱ</h2> 
      
    </section>

</main>

HTMLでは特に変わったことはしなくても良いので、比較的かんたんに実装できるのが嬉しい。

scroll-behavior: smoothには様々なメリットがあります。

scroll-behaviorのメリット

ランディング時のページ位置が分かりやすい

通常、URLの末尾に#(ハッシュ)を指定すると、ページの読み込み時に対応するid属性の要素までスクロールした状態で表示します。

例えば「https://example.com/article0123#introduction」のように「#introduction」というハッシュがついたリンクからページへ流入すると、ページ内のid="introduction"の要素のあるスクロール位置で表示します。

scroll-behavior: smoothを指定することによって、ページ読み込み時にid="introduction"まで滑らかにスクロールしていくので「今見ているところはページの途中にあるな」ということが視覚的にわかりやすくなります。

※Firefoxではランディング時にはスムーススクロールしません(2023年2月時点)

デモページで見てみる

フォーカス移動時も滑らかになる

scroll-behavior: smoothなら、キーボードのTabキーなどによるフォーカス移動の際にもスムーススクロールするようになります。

aタグやbuttonタグ、inputタグなどフォーカス移動ができるHTML要素はあまり多くないので、フォーカス可能な要素同士の距離が離れてしまう場合があります。
フォーカス移動した際にページ内をワープしたように見えてしまい、現在のスクロール位置がわかりにくく混乱してしまいます。

scroll-behaviorを使うことによって、この「ワープした感」を軽減できるのです。

※Firefoxではフォーカス移動時にはスムーススクロールになりません(2023年2月時点)

マウスジェスチャーツールにも対応

Chrome拡張機能などにあるマウスジェスチャー機能によるスクロール動作にも対応できます。
ページトップやページボトムの移動などの操作でも動きが滑らかになります。

※拡張機能によってはスムースにならないものもあるかも知れません

ブラウザの履歴に残る

#(ハッシュ)を利用するので、履歴がブラウザに記録されます。

scroll-behaviorのデメリット

IEに対応していない

今となってはどうでも良い…w

Easingや速度の調整ができない

ブラウザの仕様を利用するため、イージングやスクロール速度の変更はできません。

固定ナビゲーションが被ってしまう対処方法

ブラウザ上部に固定したナビゲーションなど設置しているサイトの場合、スクロールした位置にナビゲーションが重なってしまう事があります。

「ナビが邪魔してテキストが読めない」といった事になるので、固定したナビゲーションの高さ分だけスクロール位置を「ずらす」必要があります。

これまではナビゲーションの高さ分を考慮して、javascriptでスクロール位置を計算していましたが、CSSのみでも対応は可能です。

そこで便利なCSSプロパティがscroll-margin-top

:target {
    scroll-margin-top: 60px;
}

:target 擬似クラスは、#(ハッシュ)と一致するidを持つ要素です。

scroll-margin-topを指定した数値の分、スクロールコンテナの座標空間上のマージンを設けることができます。

デモページでも適用しているので、ソースを確認してみてください。

その他の実装方法

javascriptによる実装方法も紹介しておきます。

CSSによる実装のほうがメリットは多いですが、場合によってはJSによる実装も候補に入ると思います。

ケースバイケースで使い分けていくと良いですね。

javascriptで実装

const links = document.querySelectorAll('a[href^="#"]');
for ( let i = 0; i < links.length; i++ ) {
  links[i].addEventListener('click', (e) => {
    e.preventDefault();
    const targetId = e.target.hash;
    const targetElement = document.querySelector(decodeURI(targetId));
    const elementY = targetElement.getBoundingClientRect().top;
    const scrollY = window.pageYOffset;
    const offset = 60; // スクロール位置をずらす(px)
    window.scrollTo({
      top: scrollY + elementY - offset, 
      behavior: 'smooth' 
    });
  });
}

jQueryで実装

$('a[href^="#"]').on('click', function() {
  var speed = 400;
  var offset = 60; // スクロール位置をずらす(px)
  var $this = $(this);
  var href = $this.attr("href");
  var target = $(href == "#" || href == "" ? 'html' : href);
  var position = target.offset().top - offset
  $('body,html').animate({scrollTop:position}, speed, 'swing');
  return false
});

コメントを残す

メールアドレスが公開されることはありません。

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください

このサイトの管理者

ナオユ

Wordpress初心者向けにカスタマイズ方法やWEB制作のノウハウをポロッとまとめています。広告代理店→WEB制作会社→リモート勤務になり在宅ワークしながらアフィリエイトなど副業に挑戦中|子ども大好き新米パパ@H29男児|フラット35で実家を建て直し親と同居|仮想通貨投資(絶賛含み損w)