サンプルデモ
指定した位置までスクロールするとボタンが出現し、クリックするとページの最上部までスムーズにスクロールします。フッターなどのコンテンツがボタンに隠れないよう、最下部に来た時にはボタンが消えるようにしましょう。
スクロールすると右下にスーっと出てくるページトップへの移動ボタン。あれってとても便利ですよね。今回はこの「TOPへ戻るボタンの作成方法」を、JavaScript初心者でも理解できるように解説します。
指定した位置までスクロールするとボタンが出現し、クリックするとページの最上部までスムーズにスクロールします。フッターなどのコンテンツがボタンに隠れないよう、最下部に来た時にはボタンが消えるようにしましょう。
ここからは、「TOPに戻るボタン」の具体的な制作方法について、説明していきます。
まず必要となるのが、右下に出現するページトップへ移動するためのボタンです。HTMLとスタイルシートで、簡単に作っておきましょう。下記はサンプルです。クリックしても何も起こりません。
デザインは後から変更できるので、最初はシンプルなもので十分です。サンプルのHTMLとスタイルシートは下記にあります。周りを囲むコンテナ(div
タグ)にはpage-top
、矢印を囲むa
タグにはmove-page-top
というid
属性値を付けており、これらは後ほど、JavaScriptで要素を操作するためのIDとなります。それぞれのクラス属性値はデザイン上の役割を果たします。
HTML
<div id="page-top" class="page-top">
<p><a id="move-page-top" class="move-page-top">▲</a></p>
</div>
CSS
.page-top
{
margin: 0 ;
padding: 0 ;
}
.page-top p
{
margin: 0 ;
padding: 0 ;
position: fixed ;
right: 16px ;
bottom: 16px ;
}
.move-page-top
{
display: block ;
background: #D36015 ;
width: 50px ;
height: 50px ;
color: #fff ;
line-height: 50px ;
text-decoration: none ;
text-align: center ;
-webkit-transition:all 0.3s ;
-moz-transition:all 0.3s ;
transition:all 0.3s ;
}
.move-page-top:hover
{
opacity: 0.85 ;
}
サンプルのボタンにカーソルを合わせると、じんわりと色が変わります。普通だったら「パッ」と変わってしまいますよね?この「じんわり」を実現するために、スタイルシートのtransition
を利用しました。下記3行の、それぞれの0.3
の数値を変更することで、じんわり具合を調整できます。
CSS
.move-page-top
{
/* 〜省略〜 */
-webkit-transition:all 0.3s ;
-moz-transition:all 0.3s ;
transition:all 0.3s ;
}
ボタンを常に画面の右下に配置させるには、position: fixed
を利用します。これは、「対象の要素を常に指定した場所に固定する」という命令です。固定というのは、画面をスクロールしても、ずっとその位置に止まり続けることを意味します。
right: 16px
は画面の右端から16px離れた位置、bottom: 16px
は画面の下から16px離れた位置、という指定をする命令です。仮に左上に設置したい場合は、left: 16px ; top: 16px ;
と命令してみましょう。
CSS
.page-top p
{
/* 〜省略〜 */
position: fixed ;
right: 16px ;
bottom: 16px ;
}
「ずっとボタンを表示しておいてもいい」という場合は別ですが、今時の流行りを取り入れて、ある程度のところまでスクロールした時にボタンを出現させたいですよね?なので、デフォルトではボタンを非表示にしておきましょう。display: none
を追加して下さい。
CSS
/* 〜追加分〜 */
.page-top
{
display: none ;
}
作成したボタンの機能を、JavaScriptで実装していきます。JavaScriptがちんぷんかんぷんという人が分かりやすいんじゃないかなーと、私が思う手順で説明していきますね。ちなみにライブラリとしてjQueryを利用しているので、読み込んでおいて下さい。
まず、下記の基本型を記述します。これは決まった型なので「理解」する必要はありません。「記憶」して下さい。記憶が無理なら毎回コピーすれば、その内覚えます。下記は「HTMLを全部読み込んだら実行する」という意味を持ちます。
jQuery
$( document ).ready( function()
{
// ここに命令を書く
} ) ;
例えば、「HTMLのあそこ(id="asoko"
)の色を変えてくれ」という命令を書いても、命令をするコンピュータがその部分のHTMLを読み込む(認識する)前に命令を実行してしまったら「あそこ(id="asoko"
)なんて見つからないんだけど…」となってエラーが発生してしまいますよね。
そういったことを防ぐために、「HTMLを全部読み込んでから、この命令を実行してね」と指定するのが、先ほどの型なんです。ちなみにこの型は、次の省略形です。「document(ドキュメント)」が「ready(準備)」できたら、と考えるとイメージ湧きますよね。
なのでこの型を覚えておくと、jQueryのプログラムを動かしやすいと思います。ちなみに「読み込まれる」というのは、「HTMLの構造(タグ)が読み込まれる」ことを指すのであって、「画像や動画の読み込みが完了する」ということではないのでご注意下さい。紹介した記述は、下記の通り省略することが可能です。
jQuery
$( function()
{
// ここに命令を書く
} ) ;
それでは、JavaScript(jQuery)を使って、初期では非表示状態(display: none
)になっているボタンを表示状態にさせてみましょう。非表示にしているボタンにはpage-top
というid
が付いてましたね。それを利用して、次のように命令します。
jQuery
$( function()
{
$( '#page-top' ).fadeIn( 'slow' ) ;
} ) ;
fadeInを利用することで、非表示状態の要素を、表示状態にフェードイン(じんわりと出現)させることができます。fadeOutを利用すると、逆に非表示状態にフェードアウトさせることができます。slow
からfast
に変更することで、フェードのスピードが上がります。
fadeIn
の使い方について、日本語で分かりやすく解説されています。サンプル付きなので分かりやすいですよー。fadeOut
は、fadeIn
の逆の効果です。先ほどは、読み込みが完了したら、ボタンをフェードインさせましたが、今度は「スクロールしたら」という条件でボタンをフェードインさせてみましょう。スクロールしたらボタンをフェードインさせるには、次の通り、イベントを設定します。
jQuery
$( window ).scroll(
function()
{
$( '#page-top' ).fadeIn( 'slow' ) ;
}
) ;
簡単に言うと、ウィンドウ上($(window)
)上で、スクロール(scroll
)をしたら、その()内の関数を実行するという指定です。先ほど紹介したJavaScriptを、これに書き換えて実行してみて下さい。スクロールをしたタイミングでボタンがフェードインするようになります。
$(window).scrollTop()
で、スクロール量をピクセル単位の数値で取得することができます。数値は、「現在見ている画面の一番上が、そのページの最上部から何ピクセル離れているか」を意味します。この数値を利用することで、どのタイミングでボタンが出現するかを調整することができます。
スクロールした瞬間にボタンが出現するだけじゃ意味がありませんね。「1,500pxの距離だけスクロールしたらボタンが出現する」「1,500px以下なら逆にボタンを消す」という条件、処理を加えてみます。スクロールイベントで行なう処理を次の通り、変更しましょう。
jQuery
// 最上部から現在位置までの距離を取得して、変数[now]に格納
var now = $( window ).scrollTop() ;
// 最上部から現在位置までの距離(now)が1500px以上だったら
if( now > 1500 )
{
// [#page-top]をゆっくりフェードインする
$( '#page-top' ).fadeIn( "slow" ) ;
}
// 1500px以下だったら
else
{
// [#page-top]をゆっくりフェードアウトする
$( '#page-top' ).fadeOut( 'slow' ) ;
}
さて、最下部までスクロールした時にボタンが右下に固定されていると、フッターにあるメッセージが隠れてしまうケースがあります。それを解消するために、「最下部まで来た時はボタンを消す」という条件を加えてみましょう。これはプログラムではなく、算数の問題となります。
最下部に来たことを判定するには、まず「ページ全体の高さ」を$( 'body' ).height()
で取得します。
$(window).height()
で「画面の高さ」を取得することができます。「ページ全体の高さ」から「スクロール量と画面の高さの合計値」を引くことで、「最下部からの距離(px)」を取得することができますね。
「最下部からの距離が200px以下の場合はボタンを消す」という条件を加えると、コードが次のようになります。
jQuery
// 最上部から現在位置までの距離を取得して、変数[now]に格納
var now = $( window ).scrollTop() ;
// 最下部から現在位置までの距離を計算して、変数[under]に格納
var under = $( 'body' ).height() - ( now + $(window).height() ) ;
// 最上部から現在位置までの距離(now)が1500以上かつ
// 最下部から現在位置までの距離(under)が200px以上だったら
if( now > 1500 && 200 > under )
{
// [#page-top]をゆっくりフェードインする
$( '#page-top' ).fadeIn( 'slow' ) ;
}
// 1500px以下だったら
else
{
// [#page-top]をゆっくりフェードアウトする
$( '#page-top' ).fadeOut( 'slow' ) ;
}
いよいよ仕上げです。最後に「ボタンをクリックしたらトップまで戻る」という機能を実装してみましょう。この章までの内容で、「TOPへ戻るボタン」が完成します。
クリックイベントは下記の通り設定することができます。move-page-top
というIDを持つ要素をクリック(click
)すると、()内の関数が実行されます。
jQuery
$( '#move-page-top' ).click(
function()
{
// [id:move-page-top]をクリックしたら起こる処理
}
) ;
瞬間的な移動ではなく、ゆっくりとスクロールするようにTOPに戻るには、下記の命令を加えます。scrollTop
はページの最上部を表し、「そこから0px
の位置まで、ゆっくり(slow
)と移動しろ」という命令です。
jQuery
$( 'html,body' ).animate( {scrollTop:0} , 'slow' ) ;
スクロールイベントは、とても多くの回数、処理を発生させます。スマホにおいては、スクロールが終わった時のタイミングで処理が1回実行されるのに対し、デスクトップの場合、少しでもスクロールする度に処理が実行されます。100px動かすだけでも、何十回の処理が発生してしまうというわけです。
この「TOPに戻るボタン」は、基本的に、ボタンを出現させるか、消すかの2種類の処理しかありません。何十回も同じ処理を発生させるのは無駄なので、工夫して防いでみましょう。
今までの処理だと、1,500px以上のスクロール量があった場合は、とにかくボタンを出現させる処理(fadeIn()
)を実行していましたね。逆に、スクロール量が足りない場合は、とにかくボタンを非表示にさせる処理(fadeOut()
)をしていました。言わば、何十回、何百回もの「重ねがけ」をしていることになります。これを、「まだ非表示だった場合に限り出現させる」「表示状態だった場合に限り消す」という条件を付けて、「重ねがけ」を防いでみましょう。
それには、is(:hidden)
というメソッドが便利です。対象となる要素に対し実行することで、その要素が現在、非表示状態(display: none
)か、そうでないかを判定することができます。非表示状態だった場合にはtrue
、そうでなかった場合にはfalse
の返り値を得られます。
jQuery
// [#page-top]が非表示状態かを調べる
var result = $( '#page-top' ).is(:hidden) ;
is(:hidden)
を利用して、次のように条件分岐することで、重ねがけを防ぐことができますよね!
jQuery
// [#page-top]が非表示状態かを調べる
var result = $( '#page-top' ).is(:hidden) ;
// 非表示だった場合
if( result == true )
{
// 処理 (出現させる)
}
// 非表示じゃなかった場合
else
{
// 処理 (非表示にする)
}
続いて、例えば、1秒間だったら1秒間と決めて、その期間内に次の処理が発生しないように工夫してみましょう。それには、「〜秒後に処理を実行する」という設定ができる、setTimeout()
が便利です。次のような仕組みで実現できます。
timeOut
という任意の名前の変数を用意する。初期値はnull
にしておく。setTimeout()
で「1秒後に処理を実行する」とセットする。timeOut
に適当な値を代入する。timeOut
にnull
を代入する。ちょっとややこしいですが、何回か読み直して整理して下さい。さてさて、上記のような仕組みを作った時、「timeOut
の値がnull
じゃない時間」が1秒間だけ発生するのは理解できますよね?これがミソです。「timeOut
の値がnull
じゃない時は処理をしない」という条件分岐を作れば、いいというわけです。具体的には、次のようになります。
jQuery
// グローバル変数
var timeOut = null ;
// [timeOut]が[null]の場合だけ処理をする
// ([timeOut]が[null]じゃない場合は処理をしない)
if( timeOut == null )
{
// 1秒後に、処理を実行するようセットする
timeOut = setTimeout( // [timeOut]にsetTimeout()のID値を代入する (=とにかく[timeOut]の値が[null]じゃなくなる)
function()
{
// 処理内容
// ...
// [timeOut]の値を[null]に戻す
timeOut = null ;
}
, 1000 // 1000ミリ秒 = 1秒
) ;
}
以上、ここまで説明してきたことを盛り込んで完成したサンプルプログラムが下記です。実は、これは、この記事冒頭で紹介したサンプルデモの内容となっているんです。
jQuery
// グローバル変数
var syncerTimeout = null ;
// 一連の処理
$( function()
{
// スクロールイベントの設定
$( window ).scroll( function()
{
// 1秒ごとに処理
if( syncerTimeout == null )
{
// セットタイムアウトを設定
syncerTimeout = setTimeout( function(){
// 対象のエレメント
var element = $( '#page-top' ) ;
// 現在、表示されているか?
var visible = element.is( ':visible' ) ;
// 最上部から現在位置までの距離を取得して、変数[now]に格納
var now = $( window ).scrollTop() ;
// 最下部から現在位置までの距離を計算して、変数[under]に格納
var under = $( 'body' ).height() - ( now + $(window).height() ) ;
// 最上部から現在位置までの距離(now)が1500以上かつ
// 最下部から現在位置までの距離(under)が200px以上かつ…
if( now > 1500 && 200 < under )
{
// 非表示状態だったら
if( !visible )
{
// [#page-top]をゆっくりフェードインする
element.fadeIn( 'slow' ) ;
}
}
// 1500px以下かつ
// 表示状態だったら
else if( visible )
{
// [#page-top]をゆっくりフェードアウトする
element.fadeOut( 'slow' ) ;
}
// フラグを削除
syncerTimeout = null ;
} , 1000 ) ;
}
} ) ;
// クリックイベントを設定する
$( '#move-page-top' ).click(
function()
{
// スムーズにスクロールする
$( 'html,body' ).animate( {scrollTop:0} , 'slow' ) ;
}
) ;
} ) ;
お疲れ様でした。今回作成したプログラムのコードをまとめてあります。全てのファイルを同一ディレクトリに設置し、to-top.htmlにアクセスして下さい。
ファイル一覧
ファイル名をクリックすると内容を確認できます。「Download Zip」をクリックするとファイル一式をダウンロードできます。