ライター内藤です。花粉、そして1pxと闘っているWebコーダーでもあります。
最近、立て続けに「上部固定グローバルナビゲーション」を使ったWebサイト構築に2件ほど携わりました。1件はWordPress、もう1件は手打ちの静的サイトです。改めて思ったのは「固定ナビゲーションには落とし穴がある」ということでした。
そこで、固定ナビゲーション設置に際して、私が個人的に体験した「落とし穴」と、その解決のためにやってみたことを4つほどご紹介したいと思います。
必ずしもこれが正解というわけではありませんが、同じようなことがあったときのお役に立てば幸いです。
…と、その前に。そもそも固定ナビゲーションとは何モノか、下図をご覧ください。
例としてFacebookを挙げてみました。上部に固定された青いバーの部分は、スクロールしても常に上部に固定されて消えません。
このようなナビゲーションは、一般的に下記のようなCSSで固定しているものと思われます。
/* 固定するのは「position: fixed;」です。 */
#navi {
height: 50px;
position: fixed;
z-index: 999;
}
/* スクロールする場所:固定ナビゲーションの高さ+余白をpadding-topに指定したりします。 */
#content {
padding: 60px 0 0 0;
}
これが固定ナビゲーションですね。それでは、本編をはじめます。
1. ページ内リンクの落とし穴とその回避法
#で飛ばすリンクの場合は固定ナビゲーションの高さを考慮する
当初、「<a href=”#NEWS”>ニュース</a>」で普通にページ内リンクを書いてしまいました。しかし、安直すぎました。
飛んだ先では固定ナビゲーションの高さ分だけ上にずれてしまっていたのです。
そこで、こういうCSSを使って解決しました。
#NEWS {
margin-top: -50px; /* 固定ナビの高さ分のネガティブマージン */
padding-top: 50px; /* 打ち消し用のパディング */
}
#で飛ばすリンクは固定ナビの高さ分のネガティブマージンを取れば大丈夫です。
他にいい方法があればぜひ、教えてください。
JSスムーズスクロールの場合は普通の「#」指定で大丈夫
最近ではページ内リンクで単純なaタグリンクを利用するよりも、スルスルスルっとアニメーションで動くアレ(JSスムーズスクロール)の方がよく使われますよね。
上記の経験をした私はわざわざアレのときも固定ナビゲーションの高さを移動量から差し引いてみたのですが、失敗。こちらは特にナビゲーションの高さを考慮しなくても普通の「#」指定で大丈夫なのでした。
WordPressの場合、要注意なコード
ところで、jQueryで簡単にスムーズスクロールを実現するためのコードは、ググるとすぐに出てきます。
jQuery(function() {
// #で始まるアンカーをクリックした場合に処理
$('a[href^=#]').click(function() {
// スクロールの速度
var speed = 400; // ミリ秒
// アンカーの値取得
var href= $(this).attr("href");
// 移動先を取得
var target = $(href == "#" || href == "" ? 'html' : href);
// 移動先を数値で取得
var position = target.offset().top;
// スムーススクロール
$('body,html').animate({scrollTop:position}, speed, 'swing');
return false;
});
});
引用元:jQuery とっても簡単、ページ内リンクでスムーズスクロール
http://kyasper.com/jquery-tips/
こちらは属性指定で、「#から始まるリンク」を全てスムーズスクロールにできる便利なコードです。いちいちクラス指定しなくてもいいので楽ちん、使ってみようと思いきや!
今考えてみると当然なんですが、固定ナビゲーションはどのページでも同じリンクが表示されます(ソースが同じです)。つまり、1ページを想定した単純な「#から始まるリンク」ではページをまたぐ時に正常に動作しません。
ページをまたぐリンクの場合は、同一ディレクトリであってもファイル名が必要になりますし、ディレクトリもまたぐとなれば絶対パスにすることも必要になるからです。
- 同一ディレクトリでページをまたぐリンクの例
- <a href=”index.html#NEWS”>ニュース</a>
これだと上記のJSコード「#から始まるリンク」という条件に当てはまらなくなってしまいますね。
では、リンクにindex.htmlなど該当するページ名を追加したらJSはどうなるか。教えて!Google先生!
$(function() {
$(".scroll").click(function(event){
event.preventDefault();
var url = this.href;
var parts = url.split("#");
var target = parts[1];
var target_offset = $("#"+target).offset();
var target_top = target_offset.top;
$('html, body').animate({scrollTop:target_top}, 1500);
});
});
引用元:jQuery – ヌルヌルッとページ内スクロール
http://blog.teruterubouzu.net/net-mac/1882
ありました。さすがGoogle。
ページ内に「このページのトップへ」というリンクを作るような場合はこれでバッチリ、かとも思いましたが、いちいち「現在のパーマリンク+#」という記載をしたくなかったので、上記の参考コードに少し手を加えてからヘッダで振り分けてみました。
できるだけ無駄なコードを避けるのがコーダーの使命なのです。
<?php if(is_front_page()) : ?>
<script type="text/javascript">
jQuery(function() {
$(".scroll").click(function(event){
event.preventDefault();
var url = $(this).attr("href");
var dest = url.split("#");
var target = dest[1];
var target_offset = $("#"+target).offset();
var target_top = target_offset.top;
$('body,html').animate({scrollTop:target_top}, 800, 'swing');
return false;
});
});
</script>
<?php else : ?>
<script type="text/javascript">
jQuery(function() {
$('a[href^=#]').click(function() {
var speed = 800;
var href= $(this).attr("href");
var target = $(href == "#" || href == "" ? 'html' : href);
var position = target.offset().top;
$('body,html').animate({scrollTop:position}, speed, 'swing');
return false;
});
});
</script>
<?php endif; ?>
こうして内藤は固定ナビゲーションのイレギュラーな使い方で落とし穴にハマりつつ、なんとか脱出したのでした。
LIGはWebサイト制作を支援しています。ご興味のある方は事業ぺージをぜひご覧ください。