8/30〜|ライターのダイチが運営している個人メディア「ダイブログ」とPENGIN BLOGを統合しました

【jQuery】ページ内スムーススクロールの作り方を解説

お知らせ

当記事の元サイト「ダイブログ」は、8/30〜「PENGIN PLOG」と統合しました。
※元ドメイン(https://daib-log.com/〜)からはリダイレクト処理されます。

どうも、ダイチです。

今回は多くのWebサイト・アプリに導入されている「スムーススクロール」の実装方法をまとめました。

記述パターンもそんなに多くないので、コードをストックしておけば様々なWebサイトで使いまわしできます。

ほぼjQueryの解説記事にはなりますが、今回もさくっとコピペで実装できるようコード付きで紹介していきます。

スムーススクロールとは

ページ内リンク(アンカーリンク)をクリックすると、該当箇所にスッーと時間をかけて移動する演出のことです。

Image from Gyazo

何も仕掛けがないと下のGif画像のように一瞬でパッと遷移するわけですが、ユーザーは「移動した」という実感がありません。

Image from Gyazo

こうなると、ページ内に用意したコンテンツも見られないことになるため、サイトの離脱、直帰率が上がってしまう可能性があります。

多少時間をかけてスクロール移動することで、ユーザーが「移動してる」と実感できると共に、ページ内に「他にもコンテンツがあるのか」と感じてもらえることで、直帰率の低減に繋げられます。

そういう意味でも、縦スクロールがあるWebサイトの多くに導入されているのではないかと思っています。

※ちなみに「スムーズスクロール」と読むこともありますが意味は同じです。(smoothをどう日本語読みするか、という違いです)

今回はこちらのデモサイトを元に作成していきます。

DEMO

HTML/CSS

ここに関しては特に説明しませんが、固定ヘッダーと高さ120vhのセクションを5つ用意しています。右下にはトップへ戻るボタンを設置しています。

HTML

<header>
    <nav>
      <ul class="header-inner">
        <li><a href="#section1">section1</a></li>
        <li><a href="#section2">section2</a></li>
        <li><a href="#section3">section3</a></li>
        <li><a href="#section4">section4</a></li>
        <li><a href="#section5">section5</a></li>
      </ul>
    </nav>
  </header>
  <main>
    <section id="section1" class="section">section1</section>
    <section id="section2" class="section">section2</section>
    <section id="section3" class="section">section3</section>
    <section id="section4" class="section">section4</section>
    <section id="section5" class="section">section5</section>
    <p class="back-btn"><a href="#">Topに戻る</a></p>
  </main>

CSS

* {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
  list-style: none;
  text-decoration: none;
}
.header-inner {
  position: fixed;
  top: 0;
  display: flex;
  justify-content: space-around;
  align-items: center;
  width: 100%;
  height: 80px;
  background-color: rgb(31, 44, 223);
}
.header-inner li {
  width: 100%;
  line-height: 80px;
  text-align: center;
  transition: .5s;
}
.header-inner li:hover {
  background-color: rgb(122, 130, 243);
}
.header-inner li:not(:nth-of-type(5)) {
  border-right: 1px solid #fff;
}
.header-inner li a {
  display: block;
  color: #e8e8e8;
}
@media screen and (max-width: 480px) {
  .header-inner li a {
    font-size: 12px;
  }
}
.section {
  width: 100%;
  height: 120vh;
  padding: 100px 0;
  display: flex;
  justify-content: center;
  font-size: 40px;
  background-color: #b5b5b5;
}
.section:nth-of-type(even) {
  color: #e8e8e8;
  background-color: #302f2f;
}
.back-btn {
  position: fixed;
  bottom: 20px;
  right: 20px;
  transform: translateX(-50%);
  width: 120px;
  height: 50px;
  line-height: 50px;
  text-align: center;
  background-color: rgb(31, 44, 223);
  border-radius: 16px;
}
.back-btn a {
  display: block;
  width: 100%;
  height: 100%;
  color: #e8e8e8;
  border-radius: 16px;
  cursor: pointer;
  transition: .3s;
}
.back-btn a:hover {
  background-color: rgb(122, 130, 243);
}

jQueryコード全体

$(function () {
  $('a[href^="#"]').click(function () {
    var href = $(this).attr("href");
    var target = $(href == "#" || href == "" ? 'html' : href);
    var position = target.offset().top;
   var speed = 500;
    $("html, body").animate({
      scrollTop: position
    }, speed, "swing");
    return false;
  });
});

順に解説していきます。

クリックしたアンカーリンクを取得する

$('a[href^="#"]').click(function(){

「aタグをクリックした時は~する」というイベントの書き出しからです。

属性(aタグだったらhrefやtarget)を取得するために[ ]で囲んでいます。

この [href^=”#”] ってのを見てウッとなった初学者の方は僕だけじゃないと思いたいんですが、これは「href が#から始まる要素を取得する」という記述になります。

「〇〇が××から始まる」という指定をするときに 〇〇^=×× で記述するわけですね。

※一部の解説記事では#をダブルクォーテンションで囲まない記述を紹介しているものもありますが、これだとjQueryのバージョンによっては動かないです。最新(2020年7月時点)の3.5.1ではダブルクォーテンションで囲まないと動きませんでしたのでご注意ください。

ちなみにこれはCSSの指定でも使えます。

取得したリンク先を変数に代入する

ここから4つの変数を設定します。

$(this).attr(“href”) とは

var href= $(this).attr("href")

クリックしたaタグのリンク先(href)の中身を取得(attr)して、定義した「href」という変数に代入する。

href=”#section1”であれば、変数にsection1が代入されます。

$(href == “#” || href == “” ? ‘html’ : href) とは

var target = $(href == "#" || href == "" ? 'html' : href);

またウッとくるやつですね。

href == “#” || href == “” と ? ‘html’ : href で分解してみます。

href == “#” || href == “”

href == “#” || href == “”

href == “#” or href == “”

hrefに入っているのが「#」または「空白」

ということを言っています。このへんはjsの基礎知識なので知っておかないといけないですね。

? ‘html’ : href

「?」は三項演算子といって、if文を短縮する時などに用いられます。

式の答えとして:(セミコロン)で区切った値が、正の時は左(’html’)、誤の時は右(href)の値が入ります。

if (href == "#" || href == "") { var target = $('html'); } else { var target = $(href); }

分解して書くとこうなります。

変数targetに代入する内容は?

hrefに入っているのが「#」または「空白」の時は「’html’」を、どちらでも無ければ定義していた変数「href」の値(#section1など)

ということですね。ちなみにここで言う「’html’」はページのトップの事になります。

今回のHTMLだと、liタグ内のナビには#sectionと指定し、右下のトップへ戻るボタンは#のみ記述をしています。

ページ上部からの距離を取得した値を変数に代入

var position = target.offset().top;

offset()は指定した要素のドキュメント左上からの距離を取得します。offset().topとすると上からの距離を取得します。

aタグをクリックして取得したid=#××が代入された変数「target」の、ドキュメント上部からの距離を変数「position」に代入する、という式になります。

スムーススクロールのスピードを設定

var speed = 500;

スクロールスピードの時間を変数「speed」に代入しています。これは後ろに記述しているanimate関数の時間指定で使用します。

ちなみに1,000=1秒なので、アンカーリンクから移動先まで0.5秒間かけて移動するという時間指定になります。数字が大きくなるとそれだけゆっくり移動する、ということです。

animate関数に直接速度指定を記述してもいいのですが、後々変更する場合変数でまとめておいたほうが管理しやすいです。

ここまでの変数の意味と流れを整理します。

  1. href = クリックしたaタグに記述されているidの中身(#×× or # or 空白)
  2. target = 変数hrefのif式の結果(#××かhtml)
  3. position = 変数targetのドキュメント上部からの距離
  4. speed = スクロールが完了するまでの時間

変数の値を元にアニメーションメソッドで動きを制御

$("html, body").animate({scrollTop:position}, speed, "swing");

$(“html, body”)と指定することで、ページのトップ位置を指定することになります。

ちなみにhtmlとbody両方指定するのは、ブラウザによって対応しているのがどちらか片方だからです。

また、animate関数の仕様はanimate(properties, [duration], [easing], [complete])です。[duration]以降の第二引数からは省略可能です。

properties(第一引数)

properties(プロパティ)にはCSSプロパティや、アニメーションで動きを加えたい内容を記載します。スムーススクロールにはscrollTopメソッドを記述します。

scrollTopは、「scrollTop()」とすると指定した位置(今回だったらブラウザ上部)からのスクロール量を取得し、()内に数値が入るとその位置まで移動する、というものです。

今回はここの数値を変数position(変数targetのドキュメント上部からの距離)で取得していますので、この位置まで移動することになります。

duration (第二引数)

durationはアニメーション開始から終了までの時間を指定します。

今回は変数speedがその数値になりますので0.5秒ということになります。

easing (第三引数)

easingはアニメーションの実行速度に緩急をつけるもので、「linear」だと一定速度で動き、「swing」だと始めがゆっくりで後半早くなります。デフォルトだとこの2種類から選択することになります。

今回はswingを選択しています。

スムーススクロールのjQuery実装まとめ

  1. クリックしたaタグのhrefの中身を取得
  2. 中身が#のみ、もしくは空白だったら高さ0、#idが取得できたらページトップからの位置(高さ)を取得
  3. 現在位置から取得した高さ(0〜)まで500ミリ秒かけて移動

こんな感じの動きをjQueryで指定しているということですね。これで完成です!

まとめ

いかがでしたでしょうか?

このスムーススクロールのコードをググると、実はほぼ同じ内容が紹介されていたりします。

ただちょっとした修正を加えたい時は一つ一つの意味をザックリとでも理解しておくことが重要なので、コピペだけで済ましていた方は一度見直してみましょう。

また、スクロール繋がりで、画面領域に入ったら要素をふわっと表示させる実装方法もまとめていますので、気になるかたは是非。

スクロールしたらふわっと表示されるアニメーションの実装方法(コピペ可)

また、当記事を読まれている方の中にはWeb制作初学者の方もいるかと思います。デザインやコーディングの基礎知識を学びたい方向けの記事を用意しているので是非見ていってください!

PENGIN無料コーディング課題

【デザインカンプ無料配布】未経験からのコーディング学習ステップ

オススメ書籍紹介

【初学者向け】書籍でWeb制作を学ぶ!オススメ書籍をジャンル別に紹介! Web制作のおすすめ本24選!(コーディング・Webデザイン)

オススメUdemy講座紹介

Udemyオススメ講座まとめ 【2021年8月】Udemy×Web制作!オススメ優良講座を紹介!