画面をスクロールしたら「ページトップへ戻る」ボタンがフワッと現れ、
下までスクロールしていくとフッター辺りでピタッと止まるという例のあれ。
ちょっとした機能のわりにはまあまあ面倒くさい作業の一つです。
何故面倒くさいかと言うと、
サイトのデザインによって、コンテンツやフッターとの位置関係が様々なため、
毎回同じスクリプトを微妙に使えなかったりするからです。
レスポンシブだったりするとさらに面倒くささが増します。
これだけの事に時間を使いたくないので、
ボタンの位置やフワッとするアニメーション等はCSSに完全にまかせる形にして、
表示、非表示、止める、の切り替えは、jQueryのコードをポンと貼り付けるだけで実現できないかと思い、考えました。
DOMを弄る場合、やはりjQueryが楽です。
HTMLとCSSを準備
とりあえずサンプルとして、こんなページを用意しました。
1 2 3 4 5 6 |
<body> <header class="header">ヘッダー</header> <main class="contents">コンテンツ</main> <div id="pagetop" class="pagetop"><a href="#">ページトップへ戻る</a></div> <footer class="footer">フッター</footer> </body> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
body { text-align: center; } .header { height: 200px; margin: 0 0 20px; padding: 20px; border: 1px solid #000; } .contents { height: 5000px; margin: 20px 0; padding: 20px; border: 1px solid #000; } .footer { height: 400px; padding: 20px; border: 1px solid #000; } .pagetop { position: fixed; right: 30px; bottom: 50px; } .pagetop a { color: #fff; text-decoration: none; display: block; padding: 15px; background: #00f; } |
特別な事は何もしていません。かなり適当です。
ページトップボタンだけ、とりあえずposition:fixedにしてある状態です。
CSSでボタンの位置とアニメーションを設定
ボタンの位置とアニメーションをCSSで設定していきます。
今回、表示非表示等の切り替えは、jQueryでクラスを切り替える事で実現していきますので、
ボタンが表示されている状態の.showクラス、
ボタンが非表示になっている状態の.hideクラス、
ボタンがフッターで止まっている状態の.staticクラス
フワッとさせるアニメーションのキーフレーム
を、それぞれ設定していきます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
.pagetop { /* ↓追加 (ほぼアニメーションの為の設定です。デフォルトは非表示にしておきます。) */ height: 0; opacity: 0; overflow: hidden; animation-duration: .5s; } .pagetop a { /* 省略 */ } .pagetop.show { /* ボタン表示の状態 */ height: auto; opacity: 1; animation-name: fadein; } .pagetop.hide { /* ボタン非表示の状態 */ height: 0; opacity: 0; animation-name: fadeout; } .pagetop.static { /* フッターで止めた時の状態を設定 */ position: absolute; bottom: auto; margin: -100px 0 0; } @keyframes fadein { /* ボタン表示のキーフレーム */ 0% { height: 0; opacity: 0; } 1% { height: auto; opacity: 0; } 100% { opacity: 1; } } @keyframes fadeout { /* ボタン非表示のキーフレーム */ 0% { height: auto; opacity: 1; } 99% { height: auto; opacity: 0; } 100% { height: 0; } } |
意外と長くなってしまいましたが、ほとんどがフワッとさせるアニメーションのための設定です。
何故display:noneじゃなく、heightを0にしたりしてるのかと言いますと、
フワッと表示させるだけなら、display:none/blockの切り替えとopacityだけで実現できるのですが、
非表示にする時は、このようにしないとフワッと消えてくれないのです。
フワッと表示→パッと非表示 という動きにする場合は、displayとopacityをキーフレームで動かすだけで可能です。
その場合は、.pagetopのoverflow:hidden;も必要なくなります。
このCSSは今回のサンプルページのためのCSSなので、
実際のCSSは、当然ですがサイトによって変わります。
必要なのは、
.showで表示した時の状態を設定
.hideで非表示の時の状態を設定
.staticで止まった時の状態を設定
というルールだけです。
下記のサンプルページを見ると、ページトップが表示されていませんが、
デベロッパーツールを使用してpagetopのタグにshowやhideやstaticを追加してみて、
クラスが切り替わった時にどうなるかを確認してみると良いと思います。
jQueryで切り替え処理を書く
あとは、jQueryでクラスを切り替える処理を書くだけです。
ですが、問題はどのようにしてフッターで止める位置を判定するかです。
今までは、まずフッターの位置やウィンドウの高さを取得して、ボタンを止める相対的な位置を指定し、
レスポンシブの場合はリサイズイベントでフッターの位置、ウィンドウの高さを再取得して、スマホデザイン用のボタンの位置も指定し…
というような事をしていました。
それがおそらく普通のやり方だとは思いますが、
デザインやコーディングの仕方によっては、ボタンを止める位置の判定と実際に止まった時のボタンの位置が微妙にずれたり、なかなかすんなりと行かない事がよくありました。
このスクロール位置の判定をもっと簡単に、且つ汎用的にするために、ページトップボタンを2つ複製して、2つのクローンの位置関係で判定するようにしてみました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
// クラス名の設定 var showClass = 'show'; var hideClass = 'hide'; var staticClass = 'static'; // クローンを隠すためのCSS var hideCSS = { 'z-index': '-1', 'visibility': 'hidden' } // ページトップボタンを表示するスクロール位置を設定 var pagetopShowTrig = 1500; // ページトップボタン var pagetop = $('#pagetop'); // ページトップボタンのクローンその1。クラス.staticを追加して、ボタンが止まった時の状態のものを作る。 var pagetopCloneStatic = pagetop.clone().attr('id', '').addClass(staticClass).css(hideCSS); // ページトップボタンのクローンその2。クラス.showを追加して、常に画面固定されている状態のものを作る。 var pagetopCloneFixed = pagetop.clone().attr('id', '').addClass(showClass).css(hideCSS); // クローンをDOMに追加。見た目上は隠れています。 pagetop.after(pagetopCloneStatic, pagetopCloneFixed); // スクロールイベント $(window).on('load scroll', function() { var scroll = $(window).scrollTop(); // ボタンの表示非表示の位置の判定。 // スクロール位置がpagetopShowTrigの値以上なら、#pagetopに.showを追加。 if(scroll >= pagetopShowTrig) { if(!pagetop.hasClass(showClass)) { pagetop.addClass(showClass).removeClass(hideClass); } } else { if(pagetop.hasClass(showClass)) { pagetop.removeClass(showClass).addClass(hideClass); } } // ボタンを止める位置の判定。 // 静止状態のクローン1の位置より、画面固定のクローン2の位置の値が大きければ、.staticを追加する。 if(pagetopCloneStatic.offset().top <= pagetopCloneFixed.offset().top) { if(!pagetop.hasClass(staticClass)) { pagetop.addClass(staticClass); } } else { if(pagetop.hasClass(staticClass)) { pagetop.removeClass(staticClass); } } }); |
フッターの位置やウィンドウサイズの取得や、数値計算を全くしていない所がポイントかと思います。
見た目の部分はCSSに任せているので、レスポンシブにもこのままで対応できます。
全面的にjQueryを使用しているので、多少処理が重たいかもしれませんが、
おそらく大きな問題にはならないレベルではないかと思っています。
必要に迫られたら、scrollイベント内で無駄にメソッドを使用しないような作りにするかもしれません。
一応、コピペ用のコメント無しのコードも載せておきます。
当然ですが、jQueryの本体も読み込む必要がありますので、
HTMLも含めた全てのコードはサンプルのファイル(sample_3.html)をご参照ください。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
var showClass = 'show'; var hideClass = 'hide'; var staticClass = 'static'; var hideCSS = { 'z-index': '-1', 'visibility': 'hidden' } var pagetopShowTrig = 1500; var pagetop = $('#pagetop'); var pagetopCloneStatic = pagetop.clone().attr('id', '').addClass(staticClass).css(hideCSS); var pagetopCloneFixed = pagetop.clone().attr('id', '').addClass(showClass).css(hideCSS); pagetop.after(pagetopCloneStatic, pagetopCloneFixed); $(window).on('load scroll', function() { var scroll = $(window).scrollTop(); if(scroll >= pagetopShowTrig) { if(!pagetop.hasClass(showClass)) { pagetop.addClass(showClass).removeClass(hideClass); } } else { if(pagetop.hasClass(showClass)) { pagetop.removeClass(showClass).addClass(hideClass); } } if(pagetopCloneStatic.offset().top <= pagetopCloneFixed.offset().top) { if(!pagetop.hasClass(staticClass)) { pagetop.addClass(staticClass); } } else { if(pagetop.hasClass(staticClass)) { pagetop.removeClass(staticClass); } } }); |
初めまして
サイトでjQuery.ScrollTo.jsを使用していて、急にchromedだけスクロールが動作しなくなり、
調べていてこちらにたどり着きました。
上記、参考にさせて頂きたいのですが、初心者の為、どこに記述していいのかわかりません。
javaのファイルを別で作成するのでしょうか?
前後になどいれるのでしょうか?
教えていただけたら幸いです。
よろしくお願い致します。
ブログ開設以来初めてのコメントありがとうございます。
この記事で紹介しているのは、画面の位置によってボタンの表示を切り替えるコードなので、
jQuery.ScrollTo.jsが動作しなくなった事には関係が無いかもしれません。
Chromeで動作しなくなったとの事なので、↓の記事の方が参考になるでしょうか。
【JavaScript】Chromeの最新版(61)から画面スクロール量を取得する要素がdocument.bodyじゃなくてdocument.documentElementに変わっていた事を知った。
ただ、確かに最新のChromeでスクロールの仕様が変わったんですが、
jQuery.ScrollTo.jsのコードを見ると、今回の仕様変更とは関係無さそうなんですよね。。
実際、私のChromeでは問題無く動作しました。
このブログで紹介しているコードがお役に立てるかわかりませんが、
もし使用する場合は、下記のいずれかのやり方で大丈夫です。
・HTMLファイルに直接書く(<script>タグの中に書く)
・別のJSファイルを作成して、読み込む
・既存のJSファイルに足す
もし何か既存のJSファイルがあれば、そこに足すのが普通かもしれませんね。