Written by TSUYOSHI

スムーススクロールをjQueryで簡単実装 【初心者向け ソースコードの中身も解説】

JavaScript jQuery PROGRAMMING

こんにちはTSです。

本記事では、スムーススクロールで目的の要素までスクロールする機能について、実装方法とソースコードの解説をします。

スムーススクロールは、ボタンやリンクなどの要素をクリックした際に、特定の要素までスクロールして画面を移動させる機能です。

この記事を書いている僕は、フリーランスのフロントエンドのプログラマーとして、これまで3年以上のWeb制作経験があり、HTMLやCSSのマークアップからJavaScriptのフレームワークであるVue,React,Nuxtなどフロントエンドの開発を得意としています。

スムーススクロールはjQueryを使って簡単に実装できるので、使いこなせるようにしましょう。

スムーススクロールの概要

スムーススクロールの動作は、hrefの先頭に#がついたaタグがクリックされた時に、該当のidが付いた要素までアニメーションしてスクロールさせます。
) <a href=”#first”>

具体的には、以下の手順で動作をします。

  1. aタグがクリックされた時にhrefの先頭が「#」から始まれば、要素を取得してそのOffset値(要素の位置)を取得する。
  2. 取得したOffsetscrollTopとしてアニメーションさせて画面をスクロールさせる。

GitHubのサンプルコード

サンプルコードとして、GitHubにコードを上げています。
https://github.com/it-web-life/jquery_smooth_scroll

git clone」するか、緑色の「Code」ボタンをクリックして「Download ZIP」をクリックしてダウンロードして中身を解凍してください。

ディレクトリ構成

  • 「base」ディレクトリ以下:jQueryでスムーススクロールを実装する前のベースとなるコードです
  • 「complete」ディレクトリ以下:jQueryでスムーススクロールを実装したコードです
  • complete_fixed_header」ディレクトリ以下:ヘッダーが上部に固定されている時のスムーススクロールを実装したコードです

実装前の動作は以下の通りです。
https://it-web-life.github.io/jquery_smooth_scroll/base/index.html

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

まずは、「script」ディレクトリを作成し、その中に空のファイル「script.js」を作成します。
そして、HTMLファイルにjQuery本体とscript.jsファイルを読み込ませる記述を追加します。

index.htmlファイルのbody閉じタグの前に2行scriptタグのコードを追加します。

▼index.html

  <script src="https://code.jquery.com/jquery-3.3.1.js"></script>
  <script src="script/script.js"></script>

jQueryの実装

実際にスムーススクロールのjQueryコードを追加していきます。
追加したファイル「script/script.js」に、jQueryのコードを書いていきます。

まずは、HTMLのコードが読まれた後(DOMContentLoadedイベントのタイミング)jQueryの処理を開始するために「$(function(){ });」を記述します。

$(function(){
  // ここに後で処理を追加します。
});

この中に、aタグがクリックされた時の処理を書きます。追記したコードは以下のようになります。

$(function() {
  // ①スクロールする速度
  var scrollSpeed = 500;

  // ②href属性が「#」で始まるaタグがクリックされたとき
  $('a[href^="#"]').on('click', function() {
    // ③aタグのhref属性の値を取得
    var href = $(this).attr('href');

    // ④ページの先頭へリンク指定されているとき
    if (href === '#' || href === '#top') {
      // ページトップへスクロールさせる
      $('html, body').animate({ scrollTop: 0 }, scrollSpeed, 'swing');
      return false;
    }

    // ⑤遷移先要素の位置を取得
    var offset = $(href).offset().top;
    // ⑥要素までスクロールさせる
    $('html, body').animate({ scrollTop: offset }, scrollSpeed, 'swing');
    return false;
  });
});

コメントに番号を振っているので、順番に解説します。

  • ①スクロールする速度
    aタグがクリックされて移動する位置までアニメーションをさせる時の速度(ms指定)です。今回は500ms(0.5秒)で設定しています。
  • ②href属性が「#」で始まるaタグがクリックされたとき
    「a[href^=”#”]」と指定することにより、aタグのhrefで先頭が「#」と一致する要素のみを取得することができます。
    「$(‘a[href^=”#”]’).on(‘click’,【コールバック関数】)」とすることで、コールバック関数にクリック時の処理を記載しています。
  • ③aタグのhref属性の値を取得
    「var href = $(this).attr(‘href’);」とすることで、$(this)はクリックされた要素が入り、その要素のhref要素の値を変数「href」に入れています。
  • ④ページの先頭へリンク指定されているとき
    <a href=”#”>」や「<a href=”#top”>」のときは、「$(‘html, body’).animate({ scrollTop: 0 }, scrollSpeed, ‘swing’);」によって、ページトップへスクロールさせます。

    href=”#top” または空のフラグメント (href=”#”) を使用すると、現在のページの先頭にリンクするということがHTML仕様書で定義されています。
    https://html.spec.whatwg.org/multipage/browsing-the-web.html#scroll-to-the-fragment-identifier

    また「return false;」によって、aタグをクリックした挙動がキャンセルされています。

  • ⑤遷移先要素の位置を取得
    ③で取得したhref属性を要素(idが付いている要素)として取得し、その位置(offset)を取得しています。
    例)<a href=”#first”>〜</a>がクリックされた際は、「$(href).offset().top;」で、hrefに「#first」が入り、「$(‘#first’).offset().top;」として移動先のidが振られている要素を取得して、offset値を取得しています。
  • ⑥要素までスクロールさせる
    $(‘html, body’).animate({ scrollTop: offset }, scrollSpeed, ‘swing’);」でoffsetに取得した要素のoffset値が入り、アニメーションでスクロール移動します。またここも「return false;」によって、aタグをクリックした挙動がキャンセルされています。

これでスムーススクロールは完成です。

スムーススクロールを実装した完成品は「complete」ディレクトリの内容になります。

スムーススクロールを実装したサンプルのURL
https://it-web-life.github.io/jquery_smooth_scroll/complete/index.html

ヘッダーが固定されて表示される場合のスムーススクロール実装

ヘッダーが固定されて、スクロールしても付いてくるようなサイトはよくあると思います。このようにヘッダーが常についてきて、そのヘッダーの高さも考慮してスムーススクロールをしなければならないケースの実装について解説します。

サンプルコードのindex.htmlでheaderタグに「fixed」classを追加すると、ヘッダーが固定されるようになっています。
例)
修正前「<header class=”header”>」
修正後「<header class=”header fixed”>

ヘッダーを固定した状態だと、普通にスムーススクロールしてもヘッダーと要素がかぶってしまい、スムーススクロールしたときにズレが生じます。
これを解消するために、ヘッダーの高さを移動するoffset値からマイナスした位置にスクロールさせる必要があります。

先ほど完成させたコードに追加します。
まずは以下のコードを追加してヘッダーの高さを取得します。今回は「.header」要素がヘッダーなのでこの高さを取得します。

  // ヘッダー要素の高さを取得
  var headerHeight = $('.header').height();
  headerHeight = headerHeight ? headerHeight : 0;

「.header」要素が取得できないときにheaderHeightがundefinedにならないように、念の為「headerHeight = headerHeight ? headerHeight : 0;」を入れています。

移動先の要素までスクロールさせる処理について、「offset – headerHeight」としてヘッダーの高さをoffset値からマイナスしてスクロールさせるよう処理を以下の用に変更します。

$('html, body').animate({ scrollTop: offset - headerHeight }, scrollSpeed, 'swing');
    return false;

これで、ヘッダーが上部に固定されているときのスムーススクロールが完成です。

変更後のコードは以下のようになります。

$(function() {
  // スクロールする速度
  var scrollSpeed = 500;

  // ヘッダー要素の高さを取得
  var headerHeight = $('.header').height();
  headerHeight = headerHeight ? headerHeight : 0;

  // href属性が「#」で始まるaタグがクリックされたとき
  $('a[href^="#"]').on('click', function() {
    // aタグのhref属性の値を取得
    var href = $(this).attr('href');

    // ページの先頭へリンク指定されているとき
    if (href === '#' || href === '#top') {
      // ページトップへスクロールさせる
      $('html, body').animate({ scrollTop: 0 }, scrollSpeed, 'swing');
      return false;
    }

    // 遷移先要素の位置を取得
    var offset = $(href).offset().top;
    // 要素までスクロールさせる (ヘッダー高さ位置調整)
    $('html, body').animate({ scrollTop: offset - headerHeight }, scrollSpeed, 'swing');
    return false;
  });
});

ヘッダー固定時のスムーススクロールを実装した完成品は「complete_fixed_header」ディレクトリの内容になります。

ヘッダー固定時のスムーススクロールを実装したサンプルのURL
https://it-web-life.github.io/jquery_smooth_scroll/complete_fixed_header/index.html

まとめ

今回はスムーススクロールの実装を解説しました。
スムーススクロールは基本的な機能で、使う機会が多いと思うので、すぐに使えるようにストックしておくとよいと思います。

ご参考になれば幸いです。

※当サイトでは一部のリンクについてアフィリエイトプログラムを利用して商品を紹介しています