10年以上稼働中のWordpressで作成したサイトの「ページトップへ戻る」ボタンが正常に動かなくなっていたので原因を調べたのですが、原因と対処法の備忘録です。
原因:Akamaiのせいでした
最初に今回の原因を述べますと、Akamaiのせいでした。
Akamaiとは…
サーバーやネットワークなどインターネットを根幹で支える世界的企業。大容量のコンテンツをインターネット上で大量配信するためのネットワーク(CDN)やセキュリティに関する事業が主軸。
header.phpの記述を確認していましたら、記述した覚えのない以下の記述がありました。
<script src="https://basefile.akamaized.net/copen/5a83fd2862d15/slidebars_v1.min.js"></script>
<link rel="stylesheet" type="text/css" href="https://basefile.akamaized.net/copen/5a83fd372d9e9/slidebars_v1.css">
<script type="text/javascript" src="https://basefile.akamaized.net/stockh0lm/5ab536bcb23cf/Velocity.js"></script>
<script type="text/javascript" src="https://basefile.akamaized.net/stockh0lm/5ab7bdde91e65/jquery.inview.min.js"></script>
こちらで読み込んでいるCSSに window.scrollTop() が効かなくなってしまう原因とされている以下の記述がありました。
- body に overflow:hidden を指定している
- html や body に width・height:100% を指定している
そもそも記述した覚えがない…ので上記のAkamaiの記述をまるっと削除したところ、window.scrollTop() が正常に値を取得できるようになり問題解決しました。
問題の解決はしましたが、そもそも10年以上前のjQueryコードのままでしたので、jQueryのバージョンなどなど最新バージョンに差し替えてしまおうということで以下の対策をしました。
jQueryのバージョンを変更
はじめは、jQuery-1.8.3を利用していました。
が、色々な部分でバグが起きていたのでちょうどよい機会だなと思い、2023年9月時点で最新版のjQuery-3.7.0を適応させてみました。
以下はCDNを使う方法です。以下のようにhead内に記述します。
<head>
<title>ページのタイトル</title>
<meta charset="UTF-8">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.0/jquery.min.js"></script>
</head>
Google CDN、Microsoft CDNなどなど…4種類ほどございますが、一番有名どころのGoogle CDNを利用しています。
jQueryコードを改修
jQueryを最新バージョンに変更しましたので、コードも改修しました。
修正前のコードと修正後のコードを以下に載せておきます。
▽ビフォー
$(function() {
var topBtn = $('#back-top');
topBtn.hide();
//スクロールが100に達したらボタン表示
$(window).scroll(function() {
if ($(this).scrollTop() > 100) {
topBtn.fadeIn();
} else {
topBtn.fadeOut();
}
});
//スクロールしてトップ
topBtn.click(function() {
$('body,html').animate({
scrollTop: 0,
}, 500);
return false;
});
});
▽アフター
jQuery(function($) {
const topBtn = $('#back-top');
topBtn.hide();
//スクロールが100に達したらボタン表示
$(window).on('scroll', function() {
if ($(this).scrollTop() > 100) {
topBtn.fadeIn();
} else {
topBtn.fadeOut();
}
});
//スクロールしてトップ
topBtn.on('click', function() {
$('body,html').animate({ scrollTop: 0 }, 500);
return false;
});
});
変更した箇所は2箇所です。
- var → const
- click() → on('click', function())
まず1つ目の変更点。
変数を指定するための var は、同じ変数名が複数あってもエラーにならなかったり、ブロックスコープに対応できないなど、バグが発生しやすい仕様となっていたため非推奨となっていました。
そのため、 再代入できるが、再宣言はできない let 、または再代入も再宣言もできない const で定義しなおします。再代入の必要がない場合は、極力 const を使うと間違いなさそうなので const を使っています。
そして2つ目の変更点。
jQuery1.7以降に追加された "on" は、さまざまなイベントへの汎用性や複数のイベントを設定できるため非常に便利です。
WordPressでjQueryを使う場合は正しい書き方に修正する
jQueryは通常「$」をつけてコードを書きますが、WordPressではデフォルトで読み込まれるjQueryは、コンフリクト(衝突)を避けるための「jQuery.noConflict()」という関数の実行により、jQueryで使う「$」は通常、使えなくなっています。
そのため、「jQuery」の記述を使わなくてはなりません。
ただ「$」で書く部分を「jQuery」にすべて書き換えるのは少々面倒なので、通常は次で紹介するような書き方でスコープを作り、その中で「$」を使って書くことが一般的となっています。
▼WordPressでjQueryを読み込む方法
jQuery(function($) {
// ここにスクリプトの処理を記述
});
▼以下のサイト様が大変詳しく記載されております。
scrollTop() メソッドの対象要素を見直す
jQueryでスクロール位置を取得するには、「scrollTop()」メソッドを使用します。
「scrollTop()」メソッドの記述方法は以下の通り。
対象要素.scrollTop();
ブラウザ全体のスクロール位置を取得するには対象要素に window を指定します。
$(window).scrollTop();
上記のように scrollTop() メソッドの対象要素が window ではなく body にしている場合に Chrome と IE と Firefox では、値を取得できないバグがあるようです。
ブラウザ判別して scrollTop を使用するタグを切り替える方法もあるようです。
ただし、webkit系 の chrome では、バージョン61以降は html 要素で取得できますが、古いバージョンでは body 要素を使う必要があるのでブラウザ判定ができなくなります…。
// safariやバージョン61より前のchrome
document.body.scrollTop
// firefoxやバージョン61以降のchrome,ie,edgeなど
document.documentElement.scrollTop
この問題点のより良い解決方法として scrollingElement プロパティを使う方法があります。scrollingElement プロパティを使えば body 要素と html 要素を分ける処理が不要になります。スクロール要素がない場合には null となるようです。
// documentのスクロール要素取得
const scrollElement = document.scrollingElement;
// スクロール位置の取得
const scrollTopValue = scrollElement.scrollTop;
だがしかし…。上記の scrollingElement プロパティは IE では使えないようです…(泣)
以下のサイト様がとても詳しく説明して下さっていました。
まとめ
「ページトップへ戻る」というプログラムだけでも、動かなくなる原因や対処方法がたくさんあって、どこを直したらいいのか分からなくなってしまいますね…(泣)
色々な原因が複合的に絡んでいる場合もあるので、こちらの備忘録が少しでもお役に立てましたら嬉しいです。
以下、今回のエラーについて参考にさせて頂いた記事になります。
本当にみなさんの記事にいつも助けられています。ありがとうございます。
comment