制作のご相談はこちら
スマホサイドメニュープラグイン「sidr」にヘッダー固定を追加

2015年07月12日

スマホサイドメニュープラグイン「sidr」にヘッダー固定を追加

久しぶりにコーディングで詰まったのでメモ。

タイトルの通り、スマホにスライドインするサイドメニューを追加し、さらにヘッダーを固定するという内容です。どちらか1つを設置するのは何のことも無かったのですが、両方合わせるとなかなかうまくいかず。(確認環境はiPhoneは7.1.1、Androidは4.2.2です)

今回作成したデモはこちらです。

サイドメニューについて

今回は「sidr」というプラグインを使用しました。
公式サイトはこちらです。Sidr – A jQuery plugin for creating side menus
※最新版のjsファイルだとAndroidに不具合が生じましたので、古いバージョンを使用しています。Androidとは相性が悪いみたいです。

実装方法

まずプラグインファイルをダウンロードし、公式サイトの説明通りに設置します。
そしてヘッダ固定のCSSを追記します。

header{
	overflow: hidden;
	position: fixed;
	top: 0;
	left: 0;
	width: 100%;
	z-index: 2;
}

この状態でページを確認すると、、、このようにコンテンツ部分がヘッダエリアにめり込みます。

sidrjs_1

コンテンツの部分のめり込み解決方法

めり込む原因はヘッダのposition:fixed;によってコンテンツがヘッダの位置を無視してしまうからです。
なので常にヘッダ分の余白を設けてあげましょう。デモでは#contentsにpadding-topで対応しています。
ここで注意なのですが、余白を設けるときはmarginではなく必ずpaddingで設定してあげてください。なぜならmarginで設定してしまうとページトップへ戻るボタンがある場合、marginは設定エリアの開始点とみなされないため、ヘッダの高さ分ずれてくれないからです。余白を設定すればこのように高さが合いますよ。

sidrjs_3

アンカーリンクのコンテンツ部分めり込み解決方法

上記のとおり、ヘッダの高さ分コンテンツに余白を与えなければならないということは、ページ内・ページ外リンクがある場合はかなり厄介です。アンカーリンクを飛び先でも常に余白を設けなければいけません。
デザイン次第でそれぞれのIDにpaddingを入れられるようであれば簡単に解決するのですが、全てがそううまくはいきません。
解決コードはこちらです。

//ページ内リンク
var headerHight = 80; //ヘッダーの高さ
$('#sidr a[href^=#]').click(function(){
    var href = $(this).attr("href");
    var target = $(href == "#" || href == "" ? 'html' : href);
    var position = target.offset().top-headerHight;
    $('html,body').animate({ scrollTop: position }, 'fast');
    $('#contents').css({ 'position': 'absolute', 'z-index':'1' });
    return;
});

端的に説明しますと、クリックしたリンクのID名を取得し、ウィンドウトップから該当IDまでの高さを取得。その高さからヘッダー分の高さを引いた値までクリックしたときにスクロールさせてねっていう指示です。
※ページトップ用のスムーススクロールも記載してますのでぜひご活用ください。

//ページトップ
$('#pageBtn a[href^=#]').click(function(){
    $('html,body').animate({ scrollTop: 0 }, 'fast');
    return;
});

サイドメニューを開いた際のposition:fixed解決方法

sidrjs_2

最後にサイドメニューを開いた際にヘッダー固定をしているとヘッダーが横にずれてくれません。sidrがそもそもヘッダー固定の対応がされていないようです。他のプラグインでヘッダー固定対応のものもあるのですが、ここまで進めていたので、スライド用のjsを追加しました。

//ヘッダー開閉
$('#simple-menu').click(function(){
    if($(this).attr("class")=="headOpen"){
        $('header').animate({left: '0'}, 200);
        $(this).removeClass("headOpen");
    }else{
        $('header').animate({left: '260px'}, 200);
        $(this).addClass("headOpen");
    }
});

メニューを開いた際にheadOpenというクラスを付与し、ヘッダーを左からサイドメニューの幅分横にずらす。すでに付与されている場合(=メニューを開いている状態)はクラスを削除し、ヘッダーのleftの値を0に戻すという内容です。これでiPhoneもAndroidも納得行く挙動になりました。

sidrjs_4

最後に

いかがでしたか。サイドメニューもヘッダー固定もスマホで最近よくありがちな機能なので、拙いソースですが、応急処置用にでもお試しくださいませ。