今回はスムーススクロールを絶対パスでも処理できるようにする方法を解説します。
よく見かける方法だと「#」で始まっている内部リンクしか処理できず、ヘッダーメニューとかだと使いづらいですからね。
よく見かけるスムーススクロールの問題点
よく見かけるスムーススクロールではリンクが「#」から始まる場合しか処理できないのが問題です。つまりリンクが「../○○.html#menu01」とか「https://○○.com/○○.html#menu01」みたいな場合だとスムーススクロールが発火しません。
ヘッダーやフッターで絶対パスの内部リンクがあることもしばしばあるのでこれだと使いづらいです。
そこで絶対パスでもスムーススクロールをできるようにコードを改良してみます。
スムーススクロールを絶対パスでやる方法
以下のコードをそのままコピペでokです。
$(function () {
$('a[href*="#"]').click(function () {
const speed = 400;
const target = $(this.hash === '#' || '' ? 'html' : this.hash)
if (!target.length) return;
const targetPos = target.offset().top;
$('html, body').animate({ scrollTop: targetPos }, speed, 'swing');
return false;
});
});
a[href*="#"]
にすることで「#」を含むリンクを処理の対象にします。
よく見かける方法はa[href^="#"]
と書いてあり、これはリンクが「#」から始まるものだけが対象なので絶対パスでは処理が起きません。なのでここをa[href*="#"]
に変えます。
$(this.hash === '#' || '' ? 'html' : this.hash)
の部分はidが「#」もしくは何もない(href=””の状態)の場合は'html'
、それ以外(idがある)ならそれを取得し、jQueryオブジェクトとして取得します。例えばidが「#menu01」なら$(this.hash);
となるので$(#menu01);
と同じみたいな感じです。
if (!target.length) return;
はエラー回避用の処理です。次の行のtarget.offset().top;
は対象の要素が存在していない場合にエラーになってしまうので、対象の要素がない場合はreturn;
で処理から抜けます。よくわからない人は【jQuery】offset().topが効かない原因と対処法!という記事で解説しているので読んでみてください。
あとは通常のスムーススクロールと同じですね。
まとめ
通常のスムーススクロールは内部リンクの場合しか処理が発生せず、ヘッダーメニューなどで絶対パスのリンクが出てくる場面では使いづらいと感じました。
よく見かけるスムーススクロールより絶対パスにも対応できるこっちの書き方のほうがいいかもですね。