ページを下まで読んでいると、上に戻りたくなるときありますよね。
そんなとき、クリックするだけで戻ると非常に便利。
だけど、スクロールするほど、コンテンツ量が無いときにも表示されていると無駄な気がする。
そんな時に便利なページトップボタンを、jQueryで実装します。
基本のHTMLの記述
まずコンテンツを記述したHTMLを用意し、戻るボタンを記述します。
ボタンは、FontAwesome で表示するので、<head>から</head>
の間に、FontAwesome のCSSをCDNで読み込みます。
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css" integrity="sha512-iBBXm8fW90+nuLcSKlbmrPcLa0OT92xO1BIsZ+ywDWZCvqsWgccV3gFoRBv0z+8dLJgyAHIhR35VZc2oM/gI1w==" crossorigin="anonymous" referrerpolicy="no-referrer" />
ボタンの位置はお好みでOKなんですが、今回のサンプルは、フッターから10px上で、右端から50pxの位置に表示するよう記載しました。
また、ボタンはちょっとだけ透過を入れ、マウスオーバーで、色が濃くなるように記述しました。
//戻るボタンを実装したHTML
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>ページトップにスクロールするボタン</title>
<!-- Fontawesome のCDNを読み込む ここから-->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css" integrity="sha512-iBBXm8fW90+nuLcSKlbmrPcLa0OT92xO1BIsZ+ywDWZCvqsWgccV3gFoRBv0z+8dLJgyAHIhR35VZc2oM/gI1w==" crossorigin="anonymous" referrerpolicy="no-referrer" />
<!-- Fontawesome のCDNを読み込む ここまで -->
<link rel="stylesheet" href="scroll.css">
</head>
<body>
<div id="page">
<header>ヘッダー</header>
<div id="wrapper">
<main>メインコンテンツ</main>
<div id="pagetop">
<a href="#"><i class="fas fa-arrow-alt-circle-up fa-3x" title="to Top"></i></a>
</div>
</div>
<footer>フッター</footer>
</div>
</body>
</html>
//上記の<head>で読み込んでいるscroll.css の記述
@charset "utf-8";
body,
html {
margin: 0;
padding: 0;
}
#page {
display: flex;
flex-direction: column;
min-height: 100vh;
justify-content: center;
}
header {
background-color: #eee;
border-bottom: 5px solid #555;
height: 100px;
text-align: center;
padding: 1rem;
box-sizing: border-box;
}
#wrapper {
flex: 1;
text-align: center;
padding: 1rem;
box-sizing: border-box;
}
footer {
margin-top: auto;
background-color: #ccc;
border-top: 5px solid #555;
height: 100px;
text-align: center;
padding: 1rem;
box-sizing: border-box;
}
#pagetop {
font-size: medium;
position: fixed;
right: 50px;
bottom: 110px;
}
#pagetop a {
color: rgba(85, 85, 85, 0.6);
}
#pagetop a:hover {
color: rgba(85, 85, 85, 1);
}
現在のHTMLの表示はこうなります。
ボタンは、〇に上向きの矢印で表示しています。
お好みのものに変えるには、FontAwesomeのサイトでアイコン検索してコードを変更してください。
classの中身を検索結果のアイコンから、コピー&ペーストして書き換えるだけです。
<i class="fas fa-arrow-alt-circle-up fa-3x" title="to Top"></i>
jQuery 本体をCDNで呼び出す
次にスクロール動作に必要なjQuery本体を、CDNでHTMLの中に読みこみます。
HTMLのヘッダーもしくはbodyタグの閉じタグの直前に記述します。
<script src="https://code.jquery.com/jquery-3.6.0.min.js" integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4=" crossorigin="anonymous"></script>
</body>
</html>
お約束として、自分の作ったjQueryのプログラムよりも前にjQuery本体を置くこと。
そうしないと、「jQueryがないよー」っていうエラーが出て動作しない。
スクロールに関してのプログラムをjQueryで記述する
今、何もしてないので、pagetopボタンが、表示されたままです。
これを、ブラウザのウィンドウが400ピクセルよりスクロールされたら、ふわっとボタンが表示する といったコードにしてみたいと思います。
//ブラウザウィンドウを500px縦にスクロールしたらボタン表示
$(function() {
var topBtn = $("#pagetop"); //idがpagetopのボタンの定義
topBtn.hide(); //ページが読み込まれた段階では、ボタンは表示しない
$(window).scroll(function() { //ブラウザをスクロールしたら
if ($(this).scrollTop() > 400) { //スクロールの距離が500pxより大きければ
topBtn.fadeIn(); //ゆっくり表示
} else {
topBtn.fadeOut(); //ゆっくり消す
}
});
});
ボタンは消えます。
ただ、現在コンテンツがなく、スクロールできないので、ここで、HTMLのmainタグにコンテンツを追加します。高さのある画像を入れてみました。
↓
スクロールして下に行くと、ふわっと表示されました。
ページ内リンクをしたいので、コードを記述する
ページ内リンクは、a要素に#かidを書いて、目的の場所にジャンプすることを言います。
長い記述のコンテンツではよく使われます。このブログでも目次で利用したりしてます。
ただ、このページ内リンクは、URLの最後に#とか#topなどのパラメータがついてしまいます。
通常のHTMLであれば、問題なく動作するページ内リンクですが、PHPで構成されたHTMLの場合、URLに#がついているだけで、同一ページリンクとはみなされず、挙動がおかしくなる場合があります。
なので、jQueryでクリックされたリンク先を判別し、同一ページ内リンクであれば、#をURLから削除してから、目的の場所に移動するといったコードを記述します。
//リンク先の判別
$(function() {
//hrefが#から始まるurlのa要素がクリックされたら
$('a[href^="#"]').click(function() {
var time = 500;
var href = $(this).attr("href"); //hrefの中身を取得
var target = $(href == "#" ? 'html' : href); //hrefが#だけならhtml
var distance = target.offset().top; //特定の要素が配置されている座標
$("html, body").animate({
scrollTop: distance
}, time, "swing"); //htmlはdistanceをtimeの時間をかけて移動する
return false; //ページ遷移しない
});
});
これでいったん、pagetopボタンをクリックしてみます。
↓
ちゃんとページ上部に移動しましたが、URLの末尾に#はありません。すっきりです。
ページ内リンクの確認をする
先ほどは、ページトップボタンの動作確認でしたが、ページ内リンクの確認も必要なのでここで行います。
まずテスト用に、HTMLにコンテンツを増やします。
a要素に書かれている内容は以下の通り<a href="#page_middle">ページ下のほうに移動したいよ</a>
これをクリックして、リンク先(「ページ下のほう」という文字)に移動し、さらにURLに#page_middleが無ければ完成です。
WordPressで使う場合
WordPressでは、jQueryをそのまま書くと、$ is not define.. なエラーが出て動作しません。
jQueryをそもそも読み込んでない場合は、まず読み込んでください。ってことですが、Wordpressにはお作法があって、あるコードを書かないとうまくjQueryが動作しません。
jQueryを動作させたい部分に以下のコードを1回書いてください。
これは「$関数の動作が先に定義されている動作に戻る。」という意味です。
var $ = jQuery.noConflict();
このコードを書いてから、普通にjQueryのコードを書くと動作するはずです。
Laravelで使う場合
Laravelではまず、jQueryを使えるようにしてあげる必要があるので、webpack.mix.js にコードを追加します。
スクロールを動作させるjQueryのコードは別ファイルに記述し保存します。
保存場所は、resources の中に js フォルダを作り、その中に scroll.js として保存します。
webpack.mix.js には、scroll.js とjQueryの2つの記述を行います。
//webpack.mix.js
mix.js('resources/js/app.js', 'public/js')
.js('resources/js/scroll.js', 'public/js')
.autoload({
'jquery':['$', 'window.jQuery'],
})
.postCss('resources/css/app.css', 'public/css', [
require('postcss-import'),
require('tailwindcss'),
require('autoprefixer'),
]);
//scroll.js ( resources\js\scroll.js )
$(function () {
var topBtn = $("#pagetop");
topBtn.hide();
$(window).scroll(function () {
if ($(this).scrollTop() > 400) {
topBtn.fadeIn();
} else {
topBtn.fadeOut();
}
});
$('a[href^="#"]').click(function () {
var time = 500;
var href = $(this).attr("href");
var target = $(href == "#" ? 'html' : href);
var distance = target.offset().top;
$("html, body").animate({
scrollTop: distance
}, time, "swing");
return false;
});
});
コードを追加後、laravel mixを再ビルドするため、npm run dev します。
//コマンド実行
npm run dev
ビルド後は、自動でbodyタグの閉じタグ上部に読み込まれます。