Gazelle
2020年03月23日更新 1052 Views

Javascript(jquery)でトップへ戻るボタンを制作する

image.png
WordPressでは一般的な画面右下にある、トップへ戻るボタンを実装してみる。簡単そうに見えるが、まともに作ろうとするとやるべきことは意外に多い。要件を洗い出すと下記となる。

  • ページ右下の固定位置に矢印を表示する
  • 滑らかなアニメーションを実現する
  • ページの一番トップにいる時は表示しない

一つずつ技術的に詰めていき解決しよう。

ページ右下の固定位置に矢印を表示

これにはposition:fixedを使用すれば良い。また矢印に関してはCSSで書くこともできるが、取り敢えずは背景を青くしておくだけとする。

HTML

<a href="#">
  <div class="gotop"></div>
</a>

SCSS(CSS)

.gotop {
  position: fixed;
  bottom: 10px;
  right: 50px;
  width: 50px;
  height: 50px;
  background-color: blue;
}

これで簡単なトップへ戻るボタンは実装できた。
image.png

形を整える

このままでは味気が無いのでそれっぽくしてやる。また、見た目の煩わしさを少しでも軽減するために背景を透過させてやる。ここではFontAwesomeから適当なアイコンを取得してきて表示させる。

<a href="#">
  <i class="fas fa-arrow-alt-circle-up gotop"></i>
</a>
.fa-arrow-alt-circle-up {
  position: fixed;
  bottom: 10px;
  right: 50px;
  width: 50px;
  height: 50px;
  font-size: 50px;
  color: rgba(0,0,255,0.2);
}

image.png
透過処理を加えたことにより主張しすぎない表示にすることができた。

ハッシュ(#)を消したい

現状態では、<a href="#"></a>にアイコンタグが囲まれていることにより、遷移後のURLにハッシュがついてしまう。この結果戻るボタンを押すと、ハッシュが消えたURLになるだけで、実際にそのページを一度のボタンで離れる事ができなくなる

これはユーザエクスペリエンスとしてはイマイチなので、ハッシュを加えずにページトップに遷移させる必要がある。これにはJavascriptでクリックイベントをハンドルしてページトップに戻してやればよい。jqueryを使って記述すると以下のようになる。

 $('.gotop').click(() => {
   $(window).scrollTop(0);
 });

Animationでぬるっとトップまで移動

一瞬でトップまで戻るのもそれほど悪くはないが、アニメーションがあるとUXとして心地良い印象を受ける

トップまでの移動量を感じられるからだろうか?一瞬で移動するとページの切り替わりでチラつくからであろうか、この心地よさの原因は上手く説明できないが、ともあれAnimationをさせてやりたい。

jqueryを導入していると、先のJavascriptをanimationメソッドを使い書き換えてやることで簡単にanimateさせる事が可能である。jquery無しでも実装は可能だが、animationの速度を容易に調整できないなど不都合も多い

$('.gotop').click(() => {
  // ブラウザによりhtmlが有効な場合とbodyが有効な場合があり。
  // 第二引数として、150msでスクロールを完了する。
  $("html, body").animate({scrollTop: 0}, 150);
});

セレクタがwindowからhtml, bodyに変更されているが、この理由はscrollTopプロパティがwindowオブジェクトに存在しないためである。

またブラウザによって有効なscrollTopの値がhtmlに対して存在するものと、bodyに対して存在するものがあるためhtmlとbodyの両方指定しておく必要がある

例えばGoogle Chromeでは$('body').scrollTopの値は常に0となり、scrollTopが0の状態から0の状態へ移動するという意味に捉えられてしまい意図通りに動作しない。

ページのトップにいる時には表示しない

必要のない時にはボタンは表示しない、あるいはdisableな状態にしておくことが望ましい。

要件として落とし込むと現在のスクロール位置がトップから一定以上離れている場合にトップへ戻るボタンを表示するということを行えばよい。どう実装すべきか?

まず、常に現在の位置を測る必要があるためscrollイベントを監視する必要がある。そして、スクロールされるごとに位置を再取得してボタンを表示するか否かを決めれば良い。コードとしては次のようになる。

const $gotop = $('.gotop');
$(window).on('scroll', () => {
  const position = $(window).scrollTop();
  if (position > 400) {
    $gotop.show();
  } else {
    $gotop.hide();
  }
});

ただこれだとぱっと消えて、ぱっと表示されるため、チラつきがありあまり美しくない。show('slow')などのfadeオプションが存在するものの、表示のされ方がイマイチであったため代わりにfadeIn, fadeOutを使う

if (position > 400) {
  $gotop.fadeIn();
} else {
  $gotop.fadeOut();
}

また、最初にページを表示したときはトップへ戻るボタンは非表示でないとおかしいので、消しておく。

.fa-arrow-alt-circle-up {
+  display: none;
  position: fixed;
  bottom: 10px;
  ...
}

モバイルの表示も変更

モバイル向けに矢印の出る位置を少し調整してやる。できるだけ右下にあると煩わしくない。また、colorも再調整。PCだと表示領域が大きい分目立たせる。

.fa-arrow-alt-circle-up {
  // ...略
  color: rgba(0,0,255,0.5);
  @media screen and (max-width:499px) {
    right: 5px;
    bottom: 5px;
    color: rgba(0,0,255,0.2);
  }
}

トップへ戻るボタンが完成

最終的なソースコードは次のようになった。

HTML

<i class="fas fa-arrow-alt-circle-up gotop"></i>

SASS

.fa-arrow-alt-circle-up {
  display: none;
  position: fixed;
  bottom: 10px;
  right: 50px;
  width: 50px;
  height: 50px;
  font-size: 50px;
  color: rgba(0,0,255,0.5);
  cursor: pointer;
  @media screen and (max-width:499px) {
    right: 5px;
    bottom: 5px;
    color: rgba(0,0,255,0.2);
  }
}

JS

  const $gotop = $('.gotop');
  if (!$gotop) {
    return;
  }
  $gotop.click(() => {
    $("html, body").animate({scrollTop: 0}, 150);
  });
  $(window).on('scroll', () => {
    const position = $(window).scrollTop();
    if (position > 400) {
      $gotop.fadeIn();
    } else {
      $gotop.fadeOut();
    }
  });

この実装の挙動はこのWebサイトで確認してもらえば良いだろう。

まとめ

本記事ではトップへ戻るボタンを実装する具体的な手順について紹介した。

一見簡単そうな機能ではあるが、スクロールアニメーションの調整、ハッシュを付けない方法、モバイルでの位置調整など様々な要素技術が必要なことが理解できただろうか。

この手順を参考にしつつ、画像を独自のものに変更するなどしてオリジナルなトップへ戻るボタンを作成していただければ幸いである。

関連記事

Googleスプレッドシートとスクリプト言語Google App Script(GAS)を使用して青色申告含む確定申告を行ったのでまとめ
2020年03月28日
reduxで理解すべきimmutable objectの概念を深めていく。
2021年01月19日
commit前に他のコードを実行する方法を解説
2022年04月07日
ホームへ戻る