お問い合わせはコチラから

【固定ヘッダー対応】ページ付きアンカーリンクのスムーススクロール

サイト運営

ぺらサイトでは、見出しのアンカーリンクにメニューからスムーススクロールする構成をよく見かけます。

ぺらサイト以外でもページ内の見出しにアンカーリンクをつけ、ページ外からリンクを張るケースは少なくありません。

その時に問題になることがいくつかあります。

  1. 固定ヘッダーがあるとアンカーのとび先がヘッダーに隠れてしまう
  2. アンカーリンクにページ名が入っている場合、ページ内リンクでもスムーススクロールのjsスクリプトがエラーになる
  3. ページ外のアンカーリンクへのスムーススクロールができない

smooth-scroll.jsでは対応できないの?

固定ヘッダーに対応しているjs pluginとしてsmooth-scroll.jsが良く紹介されています。

GitHub - cferdinandi/smooth-scroll: A lightweight script to animate scrolling to anchor links.
A lightweight script to animate scrolling to anchor links. - cferdinandi/smooth-scroll

確かに、smooth-scroll.jsを使うと、ほとんどの問題は解決できるし、自前でコードを書かなくていいのはメリットが大きい。

しかし、smooth-scroll.jsで唯一問題となる点があった。

ページ外アンカークリック⇒固定ヘッダーが考慮されず隠れてしまう点である。

smooth-scroll.jsで解決できること、出来ないこと
  1. 固定ヘッダーがあるとアンカーのとび先がヘッダーに隠れてしまう問題
    ⇒〇ページ内は固定ヘッダー対応可能
    ⇒✖ページ外は固定ヘッダー考慮されない
  2. アンカーリンクにページ名が入っている場合、ページ内リンクでもスムーススクロールのjsスクリプトがエラーになる問題
    ⇒〇ページ内、ページ外もOK
  3. ページ外のアンカーリンクへのスムーススクロールができない問題
    ⇒✖ページ外のスムーススクロールは未対応

①固定ヘッダーがあるとアンカーのとび先がヘッダーに隠れてしまう

アンカーリンクをクリックすると、とび先はページ先頭に表示されます。しかし、固定ヘッダーがある場合はアンカーのとび先が固定ヘッダーの下に隠れてしまいます。

この問題を解消するのは、CSSで行う方法とJSで行う方法があります。個人的にはCSSの方法は見出しの前後のリンクをクリックできなくなるなど、制限があり使いにくい印象があります。

JSによる方法は、JSのなかで飛び位置を固定ヘッダー分ずらす処理を行うものです。

通常、スムーススクロールするJSの中でとび先をずらすことで実現できます。

②アンカーリンクにページ名が入っている場合、ページ内リンクでもスムーススクロールのjsスクリプトがエラーになる

①を踏まえて、アンカーリンクのスムーススクロールを行うJavascriptは検索すると簡単に見つかります。

例えば以下のようなものです。

$(function(){
  $('a[href^="#"]').click(function(){
    let speed = 500;
    let href= $(this).attr("href");
    let target = $(href == "#" || href == "" ? 'html' : href);
    let position = target.offset().top;
    $("html, body").animate({scrollTop:position}, speed, "swing");
    return false;
  });
});

しかしこのスクリプトは、リンクにページ名などが付いている場合はエラーになります。

ページ名を付けないと外部ページのリンクが張れません。グローバルメニューやフッターなどにアンカーリンクを置く場合はページ名が必要になりますので、そちらでもエラーになります。

ページ名が入っていてもエラーにならないスムーススクロールするJavascriptが必要になります。

$(function(){
    $('a[href*=#], area[href*=#]').not(".noScroll").click(function() {

        var speed = 400, // ミリ秒(この値を変えるとスピードが変わる)
            href = $(this).prop("href"), //リンク先を絶対パスとして取得
            hrefPageUrl = href.split("#")[0], //リンク先を絶対パスについて、#より前のURLを取得
            currentUrl = location.href, //現在のページの絶対パスを取得
            currentUrl = currentUrl.split("#")[0]; //現在のページの絶対パスについて、#より前のURLを取得

        //#より前の絶対パスが、リンク先と現在のページで同じだったらスムーススクロールを実行
        if(hrefPageUrl == currentUrl){

            //リンク先の#からあとの値を取得
            href = href.split("#");
            href = href.pop();
            href = "#" + href;

            //スムースクロールの実装
            var target = $(href == "#" || href == "" ? 'html' : href),
                position = target.offset().top, //targetの位置を取得
                body = 'body',
                userAgent = window.navigator.userAgent.toLowerCase();
            if (userAgent.indexOf('msie') > -1 || userAgent.indexOf('trident') > -1 || userAgent.indexOf("firefox") > -1 ) { /*IE8.9.10.11*/
                body = 'html';
            }
            $(body).animate({
                scrollTop: position
            }, speed, 'swing', function() {
                //スムーススクロールを行ったあとに、アドレスを変更(アドレスを変えたくない場合はここを削除)
                if(href != "#top" && href !="#") {
                    location.href = href; 
                }
            });

            return false;
        }

    });
});

参考https://sterfield.co.jp/designer/%E3%83%9A%E3%83%BC%E3%82%B8%E3%83%AA%E3%83%B3%E3%82%AF%E4%BB%98%E3%81%8D%E3%81%AE%E3%82%A2%E3%83%B3%E3%82%AB%E3%83%BC%E3%83%AA%E3%83%B3%E3%82%AF%E3%81%AB%E5%AF%BE%E5%BF%9C%E3%81%97%E3%81%9Fjquery/

③ページ外のアンカーリンクへのスムーススクロールができない

javascriptのスムーススクロールは、ページ外のアンカーリンクのスムーズスクロールには対応していません。

これはよく知られた制限なのですが、解決方法も知られています。

//固定ヘッダーの指定
var headerHeight = $('#header').outerHeight();
    
// ページ外アンカーのページ付きリンクへのスムーススクロール
var urlHash = location.hash;
if(urlHash) {
    $('body,html').stop().scrollTop(0);
    setTimeout(function(){
        var target = $(urlHash);
        var position = target.offset().top - headerHeight;
        $('body,html').stop().animate({scrollTop:position}, 500);
    }, 100);
}

全ての問題を解決するアンカースムーススクロールスクリプト

いままでの①~③までの解決策をまとめたのが以下のスクリプトにになります。

脱Jqueryと叫ばれていますが、直ぐに動くものを作る方が100倍エライと私は思っていますので、Jqueryでのソリューションは今でも使えると思っています。

//固定ヘッダーの指定
var headerHeight = $('#header').outerHeight();
    
// ページ外アンカーのページ付きリンクへのスムーススクロール
var urlHash = location.hash;
if(urlHash) {
    $('body,html').stop().scrollTop(0);
    setTimeout(function(){
        var target = $(urlHash);
        var position = target.offset().top - headerHeight;
        $('body,html').stop().animate({scrollTop:position}, 500);
    }, 100);
}
// ページ内アンカーのページ付きリンクへのスムーススクロール
$(function(){
    $('a[href*="#"], area[href*="#"]').not(".noScroll").click(function() {

        var speed = 400, // ミリ秒(この値を変えるとスピードが変わる)
            href = $(this).prop("href"), //リンク先を絶対パスとして取得
            hrefPageUrl = href.split("#")[0], //リンク先を絶対パスについて、#より前のURLを取得
            currentUrl = location.href, //現在のページの絶対パスを取得
            currentUrl = currentUrl.split("#")[0]; //現在のページの絶対パスについて、#より前のURLを取得

        //#より前の絶対パスが、リンク先と現在のページで同じだったらスムーススクロールを実行
        if(hrefPageUrl == currentUrl){

            //リンク先の#からあとの値を取得
            href = href.split("#");
            href = href.pop();
            href = "#" + href;

            //スムースクロールの実装
            var target = $(href == "#" || href == "" ? 'html' : href),
                position = target.offset().top - headerHeight; //targetの位置を取得
               $('body,html').stop().animate({scrollTop:position}, 500);

            return false;
        }

    });
});

アンカーリンクが正常に動かない時は?

マウスのホイールが止まっていないと正常に動きませんので、マウスのホイールが停止していることを確認してみましょう。

まとめ

ペラサイトの場合はあまり問題にならないアンカーリンクですが、ページが増えてくると一気に問題が噴出します。

そのようなときには今回の記事を思い出して使えそうなら使ってみてください。

この記事を書いた人
ブーン

はるばる日本よりオランダ王国へやってまいりました。
自分の経験が少しでも参考になれば嬉しいです。
お問い合わせは、『こちら』からお願い致します。

\ブーンをフォロー/
スポンサーリンク
サイト運営
\シェアお願いします!/
\ブーンをフォロー/
こんな記事も読まれています

失敗しないレンタルサーバーランキング

mixhost

不正アクセスに強くて使いやすいおススメサーバー
\本サイトで利用中/
メリット①:自動ウィルス駆除対応
メリット②:サイトの表示速度が速い!
メリット③:転送量の上限が多い!
メリット④:自由にプラン変更ができ、アクセス増にも対応できる!
メリット⑤:バックアップデータが無料で復元できる!
メリット⑥:Wordpressが簡単にインストールできる!
メリット⑦:どのプランでも初期費用が無料!
メリット⑧:10日間の無料お試し期間と30日の返金保証!

Conoha Wing

国内Wordpress最速の最強サーバー
メリット①:圧倒的な表示速度
メリット②:レンタルサーバーと独自ドメインがセットでお得◎
メリット③:プラン変更はすべてのプランで自由自在
メリット④:一か月の利用転送量の制限が緩い(9TB~)
メリット⑤:WordPresサイトの移行が簡単

エックスサーバー

国内シェアNo1の安定性と実績が魅力。ALL SSDで死角なしの万能サーバー。
メリット①:サイトの表示速度が安定して速い!
メリット②:アクセス負荷に強くて安定性が高い!
メリット③:24時間365日の充実サポートで安心!電話サポートもあり!
メリット④:転送量が多い!
メリット⑤:自動バックアップ機能付き!
メリット⑥:WordPressが簡単にインストールできる!
メリット⑦:10日の無料お試し期間がある!

タイトルとURLをコピーしました