わたしと納豆ごはん

納豆、Web、雑記など

jQueryを使わず、CSSとJavaScriptで実装するトップに戻るボタン

「トップに戻るボタン」というものがあります。

ブログの右下によく表れる、押せばページ上部に戻れるアレのことです。

これを設置する場合、jQueryを使った方法が多く紹介されています。

ですが、もし「トップに戻るボタン」だけにjQueryを使っていたら、軽いとは言えないそれをわざわざ導入するのは、ちょっともったいない気がします。

シンプルにするっとトップに戻り、フェードインしながら表れるトップに戻るボタンでしたら、CSSJavaScriptだけでも簡単に実装できます。

スポンサーリンク

トップに戻るボタンは、必要か不要か

その前に「トップに戻るボタン」については不要だという意見があります。ブラウザの機能やスクロース・スワイプを使えば簡単に戻れるので、ボタン自体の意味は無いというものです。

まず、わたし自身はトップに戻るボタンをほぼ押したことはありません。押したと言えば「自分で作ったトップに戻るボタン」の動作確認ぐらいです。

なので、個人的にはあっても無くても困りませんし、必要とも感じません。

ですが、意味があるか無いかと言えば、決して意味は無いとも思いません。

例えば、こちらのサイト。

参照リンク:サントリーウエルネスオンライン

トップ(上に)に戻るボタンはスマホ版の商品説明ページで出てくるのですが、このボタン、画面を動かさず停止しているとボタン自体が薄く目立たなくなるように工夫がされています。

これを見たユーザーは「あ、読みやすいようにボタンを目立たなくさせているのだな」と感心する方もおられると思います。

これはつまり「当社はこれだけお客様に心配りをしていますよ」というアピールになっているのです。

このようにトップに戻るボタンは、訪問してきたユーザーに対して何らかのアピールができます。まあ、これだけでなくページ全体で言えることですが。

ですので、トップに戻るボタンを使って他のサイトの差別化やサイト自体の印象を高める効果を持たすことができます。

…とはいえ

今回の記事を書くにあたってサイトをいくつか調べたのですが、トップに戻るためのボタンは以前よりずいぶん減ったような感じを受けます。

トップに戻るボタンが普及したのは、iPhoneの性能がまだ低くスワイプがもっさりしていた頃だったように記憶しています。

近年のスマホは性能が良くなってきてますし、iPhoneSafariはブラウザ上部をタップすればページ上部に戻れますので、そういったことが影響しているのかもしれません。あくまで推測ですが。

結局のところ、トップに戻るボタンの設置はサイトのコンセプトやターゲットによって変わってくると思うのですのよね。

このブログでも以前は付けていましたが、意見を参考にしたり考えたりした結果、現在では外しています

スポンサーリンク

jQueryを使わないトップに戻るボタン

それではコードを紹介します。以下のものをはてなブログでしたらフッターなどに記述し、CSSをデザインなどに書き込めばボタンは機能します。

まずは、HTML と JavaScript

<!-- トップに戻るボタン -->
<div id="page-top" class="blogicon-chevron-up"></div>

<!-- ここからJavaScript -->
<script>

//スクロール量を取得する関数
function getScrolled() {
 return ( window.pageYOffset !== undefined ) ? window.pageYOffset: document.documentElement.scrollTop;
}

//トップに戻るボタンの要素を取得
var topButton = document.getElementById( 'page-top' );

//ボタンの表示・非表示
window.onscroll = function() {
  ( getScrolled() > 500 ) ? topButton.classList.add( 'fade-in' ): topButton.classList.remove( 'fade-in' );
};

//トップに移動する関数
function scrollToTop() {
  var scrolled = getScrolled();
  window.scrollTo( 0, Math.floor( scrolled / 2 ) );
  if ( scrolled > 0 ) {
    window.setTimeout( scrollToTop, 30 );
  }
};

//イベント登録
topButton.onclick = function() {
  scrollToTop();
};

</script>

そしてこちらは CSS です。

#page-top {
    font-size: 0;
    position: fixed;
    bottom: 16px;
    right: 16px;
    opacity: 0;
}
#page-top.fade-in {
    color: #000;
    font-size: 60px;
    opacity: 0.6;
    transition: opacity 1s;
}

動作確認用のサンプルページも用意しています。よろしければご確認ください。

リンク:サンプルページ

解説

以下、このコードについて解説をします。

HTML

HTMLは次のようにしています。

<!-- トップに戻るボタン -->
<div id="page-top" class="blogicon-chevron-up"></div>

ボタン用のHTMLを用意します。よくあるものですよね。

アイコンははてなブログに標準でインストールされているアイコンを使用しています。Font Awesome でも良かったのですが、今回はシンプルにこちらにしました。

ボタンを a 要素にしてページ内リンク(href="#top")を設定したほうが文法的に良いのかもしれませんが、これをするとreturn falseを指定するなどコード量が若干増えるので div 要素にしています。

CSS

ボタンの表示・非表示や、フェードインといったアニメーションはCSSで実装します。クラスfade-inを付けたり外したりすることで、それらを実行させます。

#page-top {
    font-size: 0;
    position: fixed;
    bottom: 16px;
    right: 16px;
    opacity: 0;
}
#page-top.fade-in {
    color: #000;
    font-size: 60px;
    opacity: 0.6;
    text-decoration: none;
    transition: opacity 1s;
}

要素の表示や非表示はdisplayを使うことが多いのですが、このプロパティはアニメーションをさせるときには向いていません。

代わりにfont-sizeをゼロにすることでボタンの表示・非表示を行っています。

ちなみにサンプルではシンプルにするため、最低限のCSSにしています。背景色を付けるなどデザインを追加するときは、ご自身で調整してください。

位置の取得

//スクロール量を取得する関数
function getScrolled() {
 return ( window.pageYOffset !== undefined ) ? window.pageYOffset: document.documentElement.scrollTop;
}

こちらはトップからスクロールして移動した距離、つまりスクロール量を取得するスクリプトです。

多くのブラウザ、特にスマートフォンではpageYOffsetだけでも。いけると思います。

ですが、このプロパティはIEでは機能しません。

そのためIE用にdocument.documentElement.scrollTopを含めています。

また、この方法ではIEの互換モードでは位置を取得しません。ですが、最新のIEは互換モード(ドキュメント・モード)は非推進になっています。

参照リンク:推奨されていないドキュメント モードと Internet Explorer 11 (IT 担当者向け Internet Explorer 11) - Internet Explorer | Microsoft Docs

このような事情もあり、またコード自体もシンプルにできるので、このようにしています。

ボタンの要素取得

//トップに戻るボタンの要素を取得
var topButton = document.getElementById( 'page-top' );

クラスの追加や削除、イベント登録を行うために先にボタンの要素を取得しています。

ボタンの表示・非表示

//ボタンの表示・非表示
window.onscroll = function() {
  ( getScrolled() > 500 ) ? topButton.classList.add( 'fade-in' ): topButton.classList.remove( 'fade-in' );
};

指定数値以上スクロールしたら要素にクラスを追加し、それ以下の場合はクラスを削除するようにしています。

移動する距離は500の部分で、トップからスクロールした量が500ピクセルを超えるとクラスをくっ付けるようにしています。

クラスにはフェードインしながら表示させるスタイルを指定しているので、そのクラスが付けばフェードインしながらボタンが表示されるという仕組みになっています。

トップに移動する関数

//トップに移動する関数
function scrollToTop() {
  var scrolled = getScrolled();
  window.scrollTo( 0, Math.floor( scrolled / 2 ) );
  if ( scrolled > 0 ) {
    window.setTimeout( scrollToTop, 30 );
  }
};

このコードは、こちらのものを参考にさせていただいてます。

参考リンク:[JavaScript] jQuery を使わずにスクロールでトップに戻るボタンを表示する | rakuishi.com

まず先ほどの位置を取得するスクリプトを使って、スクロール量を取得します。

  var scrolled = getScrolled();

その後、取得したスクロール量を半分に割り、その位置に移動します。

  window.scrollTo( 0, Math.floor( scrolled / 2 ) );

タイマーイベントを使って再び自分自身の関数を登録します。これにより指定時間後に先ほどと同じ処理を行います。つまり、ある時間を置いて同じ処理を繰り返す、という処理をしています。

  if ( scrolled > 0 ) {
    window.setTimeout( scrollToTop, 30 );
};

ちなみに指定できる時間の単位はミリ秒 (1/1000 秒) です。上記にかかれている数値 30 ならば 0.03 秒後に実行されることになります。

これを先ほど取得したスクロール量が 0 になるまで繰り返します。

計算式は移動距離を2で割って小数点以下は切り捨てるという計算をしています。

これにより最初は早く、後半になるにつれて速度がゆっくりになっていくように見えます。

スクロール量÷2を曲線グラフ
スクロール量÷2 でトップに戻るまでの移動距離の曲線グラフ

移動スピードは、計算式の割る数値の大きさと、繰り返し時の遅延時間によって調整できます。

スピードを遅くするなら割る数値を少なくしたり、遅延時間を長くすれば遅くなります。早める場合はその逆です。

ただし setTimeout の時間は、遅すぎたら動きがカクカクになりますし、早すぎると繰り返し処理が上手く作動しません。

また割る数値も大きくしすぎるとスムーズに動いているようには見えず、パッと上部に戻ったように見えてしまいます。

スピード調整をする場合は、これらの点を注意して行ってください。


今回の記事は以上です。

プログラムはまだまだ勉強中ですので、これでベストかどうかは分かりません。でも、けっこう短くシンプルにまとめることができたと思います。

ご指摘、ご感想があればよろしくお願いします。

何かのお役に立てれば幸いです。

スポンサーリンク