現在テストで、できるかどうかも含めてTopへ戻るボタンの位置をjQueryのみで移動させています。できるかどうかで言うとできるのですがテスト中であるというのをご了承下さい(アップデートや他の理由で元に戻すかも)。
またトップへ戻るボタンが消えてしまって表示されずに困るような場合は、PCならキーボードのHOMEボタンで、あるいはPageUp,Downを利用したり、はたまたスペースキー(PageDown)、Shift+スペースキー(PageUp)を併用することでマウスホイールをクリクリやることによる腱鞘炎の被害から多少ですが開放されます。
更に、この記事に書いてあるスクリプトはエラーこそでませんが挙動不審です。と言うのは、おそらくですが初期の位置をきちんと取れれば大丈夫ですが、adsenseや他のスクリプトの読み込みなどでその位置、その他諸々がうまく取れ無かった場合、Topへ戻るボタンがおかしな動きをします。画面下に消えていったりとかですけどね(笑)
また本来ならCSSとそれに対応するjQueryなどを設置してあれば問題ないところを、半ば強引に、まさに力技で動かしますのでそのあたりだけご了承下さい。
ただ、そこが説明したいわけではないのです。説明したいのは一番最後の方で。
本題
すでに、この記事を読んでおられるということは、ここを読む頃に気が付かれたかも知れません。Topへ戻るボタンを本文記事横にスクロールに追従するように設置してあるのです。これを実装するにあたり普通ならCSSでボタンを作って配置しますよね。なんならCSSファイル内でclassをいくつか作って移動させたい時だけjQueryなどを用いてclassを変えたりしますよね。そう、それが普通なんです。
ただどうせならそういうの無しでjQueryだけでやったらどうかと言うのがこの「Topへ戻るボタン」の位置を変えるの醍醐味です。
一応、書いたスクリプト貼っておきます。親テーマのjavascript.js内、topへ戻るボタンの処理している所は全てコメントアウトして、子テーマに今回のスクリプトを書いています。もちろんCSSファイルは何もしてません。以下のスクリプトだけです。
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 |
$(function(){ var $; $ = jQuery; var cW = $("#container").outerWidth(); if ( cW > 1148){ $("#page-top").remove().clone().prependTo("#body-in"); $("#page-top").removeAttr().css({ "position" : "relative", "margin-left" : 735 + "px", "width" : 42 + "px", "height" : 50 + "px", "z-index" : 10 }); var initial_offset = $('#page-top').offset().top; $(window).scroll(function() { var offset = initial_offset + $(document).scrollTop() + 150; ($(window).scrollTop() > 600) ? $("#page-top").fadeIn() : $('#page-top').css({"display":"none"}); $('#page-top').animate({ top: offset }, { duration: 'slow', queue: false }); }); } else { /* * #containerのサイズが1148より小さい場合 * オリジナルのtop頁へもどる処理のコピー */ jQuery(window).scroll(function(){ //最上部から現在位置までの距離を取得して、変数[now]に格納 var now = jQuery(window).scrollTop(); //最上部から現在位置までの距離(now)が600以上 if(now > 600){ //[#page-top]をゆっくりフェードインする jQuery('#page-top').fadeIn('slow'); //それ以外だったらフェードアウトする }else{ jQuery('#page-top').fadeOut('slow'); } }); } $("#move-page-top").on("click",function(){ jQuery('body,html').animate( { scrollTop : 0 }, 800 ); }); }) |
概要としては、まず#containerのサイズを見て、1148px以上であれば今回の位置にボタンが表示されるようになっています。それよりも小さい場合は、従来のTopへ戻るボタンが出るようになっているのですが、例えばPCの画面でブラウザのサイズを変えたとした時、おそらくはそのまま元のように右下に表示されずに、今回の追従型のボタンが表示されていると思うんです。サイズそのままでページを読み込み直すかすると動作します。
ここらが説明したいところなんですが、それはまだ少し先で。
ひとまずスクリプトの説明しておきます。
1 |
$("#page-top").remove().clone().prependTo("#body-in"); |
この部分だけは何かしらに使えるのではないかと思う部分です。THEチェーンメソッドと言うか、これこそjQueryというか(笑)
元々ある#page-topをremoveで消して、更にクローンして#body-inのブロックの先頭にprependToで移します。なぜ#body-inの方に移動させたかですが、元々のTopへ戻るボタンはcssにてpositionがfixedになっており、#page-topがどこに書いてあっても画面右下の定位置に表示されるようになっています。
もしこの状態で、現在の記事横にTopページへ戻るボタンを持ってくるとなると結構大変な話になってきます。なぜなら、記事が入っているのは#mainの中ですが#mainの横幅がわかったとして、どこ基準でそこに持ってくる?と言うことなんです。
#mainはfloat:leftされており、またサイドのスペースは#body-inでmarginがautoになってます。画面幅が広がればそれに応じて#mainの横幅を維持しながらスペースだけが広がっていく。その中で定位置を見つけようとすれば、左側あるいは右側どちらかのスペースの幅を見つけないと調べられないと思うので、それだったら#body-inの下に入れておけば必ず左側は#mainの左側に合うはず、と言う理由で#body-inの下にしてあります。
1 2 3 4 5 6 7 |
$("#page-top").removeAttr().css({ "position" : "relative", "margin-left" : 735 + "px", "width" : 42 + "px", "height" : 50 + "px", "z-index" : 10 }); |
ここは結構大変な箇所です。removeAttr()はおそらく必要かと思います。いらないかなぁと思いつつ、ひとまず入れてあります。それからcssの設定をしています。
ここで#mainのサイズが740pxであるのにどこから735pxが出てきたんだと思われたりするかと思いますが、実はこれちょっと考えた部分です。つまり、#mainが740pxでぴったり横にボタンを付けたい場合は、margin-leftは740pxで良いはずです。ボタンを#mainの右側ボーダーの上に設置しているので、ボタンwidth(42px:jQueryのcssで設定した幅)の半分を左にずらせばセンターになるはずです。
740px – (42/2) = 719px。ん?合わない・・・。実際にもボーダーのセンター上に配置できません。
そこでしばらく考えて、元のボタンのCSSを見てみるとright:16px…お前かっ(ΦωΦ)。そして、このright:16pxを足すと735px。この16pxがなんで合わないのかしばらく考えました(笑)
さて次は、scrollする部分。元のボタンは右下にずっとあって、スクロールで600pxほど移動したらフェードインして表示されるというものでした。今回のは、ボタンがスクロールバーに追従します。
処理を見ていただくと、ん?と思われるかも知れませんが、実はこのボタン追従はスクロールバーのtopに合わせるようになっていたのです。なっていたのですと言うのからもわかるように、ネットでちょちょいと探してきたスクリプトですが(参考: web制作記)、スクロールバーのトップ位置だとちょっと上過ぎるかなぁと思ったのと、自分がいつもだいたいページの真ん中辺りにマウスポインタを持ってきているのもあって、だいたいそのあたりで、ただあまり近すぎると誤クリックしてしまってトップへ戻ってしまうおそれがあるので、やや上あたりになるように+150ほどを調整してます。
さて、elseの後は、オリジナルのスクリプトなので特に説明もいりません。ひと通り、これでボタンの移動と画面サイズによって違う挙動をするTopへ戻るボタンをjQueryだけでやることができました。
本題の本題
このスクリプトの説明をする前に少し触れましたが、「Windowがリサイズされる時にボタンもおそらくその表示のまま」と言う話をしました。これ実は、adsenseにも言えまして、例えばサイドバーが画面横に出るサイズのいわゆるPC画面の表示でブラウザのサイズを小さくした時、画面自体はCSSの切り替えで例えばiPadあたりの表示に変わるわけですが、その時に従来のadsenseがサイドバーにトップにある場合は特に問題はありません。問題は、レスポンシブ型のadsenseなのです。
現在、うちのサイトではresponsive型のadsenseがサイドバートップに入ってます。サイズは300×600のバナーが出ています。このまま画面を小さくして行くと、サイトの表示はiPadあたりのサイズになります。しかしadsense自体はそのまま300×600のサイズで回りこんで画面下で表示されているようです。本来ならバナーが画面下に回りこめば横長のバナーに変わって欲しい所。これは逆もしかりで、iPadよりも小さいサイズにした状態から画面を広くすると、横長のバナーがサイドバートップに出てくるように思います。
こんな感じで小さい画面から大きい画面にした時に、横長バナーのまま表示される。ページのリロードをすればもちろん直る。サイドバートップにレスポンシブadsenseが入ってて、完全レスポンシブはオフ。
現在、うちのサイトではWP-SuperCacheが入っています。そのせいもあるかも知れません。ただ、何とかできるように思うんですよ。
まぁ実際には、そんな不具合(エラーでもなんでもないですけどね)が起こるのはPCだけの話なんですけども、何とか直したいなぁと。iPadやらの仕様はわかりませんが、仮に縦長で見ていた時、画面を横長に回転させてサイドバーが出れば同じことになるのではないかなぁとも思ったり。サイドバーが出るかどうかは知りませんけども(ΦωΦ)
これを直すためのキーワードでふと思いつくのは、$(window).resize。とresizeした時に、adsenceを再読み込みかなぁ、あるいは何かしらシグナルを送れば直るかも知れません。今後はこのあたりもちょっと調べられたらなぁと思ったりします。
resizeのとても良いスニペットがあるので、ひとまず今回はそれを最後に掲載しておきます。
1 2 3 4 5 6 7 8 9 10 |
var timer = false; $(window).resize(function() { if (timer !== false) { clearTimeout(timer); } timer = setTimeout(function() { console.log('resized'); // 何らかの処理 }, 200); }); |
これは、resizeする時にsetTimeoutをうまく利用して、リサイズが終わった時だけ処理をするというものです。例えばブラウザのサイズが変わっている最中は何もせず、変わった後に処理をすることで負荷がかからないと言うか無駄な処理をしないという素晴らしいアイデア。おそらくずいぶん前に見つけたような気がします。参考: CreativeStyle
元々はStackOverflowからの引用みたいですけども、こういうのはたくさん知っておきたいですね。
※ CreativeStyleさんは、新しいブログに引っ越しされたみたいです。