Fixed固定ナビゲーションを設置するときに気をつけたい4つのこと


Fixed固定ナビゲーションを設置するときに気をつけたい4つのこと

ライター内藤です。花粉、そして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; ?>

こうして内藤は固定ナビゲーションのイレギュラーな使い方で落とし穴にハマりつつ、なんとか脱出したのでした。

2. スマホの固定ナビゲーション対策にはjQuery Mobileを導入する

「特にスマホ専用の見え方はしなくていいです」というオーダーに小躍りしていた内藤。しかしクライアント様から「スマホだと固定ナビがスクロールしちゃうんですけど」という報告を受けて一転、ピンチを迎えます。

iPhoneやAndroidは、2014年3月20日現在で正式にはfixedというcssをサポートしていません。スマホでも固定にしたいので、jQuery Mobileをインクルードすることにしました。

fixedをサポートするためだけのコードを取得する方法

jQuery Mobile公式サイトにアクセスし、トップページ右側の「Custom download」ボタンをクリックします

jQuery Moble

http://jquerymobile.com/

下記の3項目にチェックを入れて…

  • Toolbars: Fixed
  • Toolbars: Fixed: Workarounds
  • Toolbars: Fixed

jQuery Mobile

一番下の「Build my download」ボタンを押します。これでスマホの固定ナビゲーション対策はひと段落しました。

3. ブラウザの印刷機能にも気を配る

これはクライアント様の確認時に先方が画面をプリントアウトされたことで発覚した問題なのですが、「印刷すると見えなくなってしまう場所があるんですけど」と言われました。

なるほど、固定されたナビゲーションが改ページごとに登場し、一部が隠れてしまっていたので、たしかにちょっと見づらいです。

そこで印刷用CSSを利用し、見えなくすることにしました。さらに、「このページのトップへ」も印刷時には見えなくていいので、こちらも見えないように対処。

#header,
#footer,
#goTop {
	display: none;
}

これでOKが出た次第です。

最近はブラウザの印刷機能にPDFで保存する機能がついていたりもして、意外に印刷用cssの重要性が高まっている気がします。

4. YouTubeの動画を埋め込む時の落とし穴とその回避法

YouTube動画の埋込コードをそのまま使っていたら、「なんか表示が変なのですぐチェックしてください!」とクライアント様から連絡が来てしまいました。

現在のChrome/Safariでは確認できない問題ですが、IE11やFireFoxでは注意が必要です。YouTubeの埋込コードを下図のように取得してそのまま使うと困ったことが起きるのでした。

YouTubeの埋込コード

これをこのまま使うと…

固定ナビゲーションの上をスクロールする

そうなんです、スクロールすると動画がz-indexを無視するように固定ナビゲーションの上を通過してしいたのです。

この現象に対しては、YouTubeから取得したコードのリンク先に、下記コードを追加することで回避可能でした。

<!-- そのままのコード -->
<iframe width="560" height="315" src="//www.youtube.com/embed/DbPAW_gKJmM?rel=0" frameborder="0" allowfullscreen></iframe>

<!-- リンクの最後に &wmode=transparent を追加する -->
<iframe width="560" height="315" src="//www.youtube.com/embed/DbPAW_gKJmM?rel=0&wmode=transparent" frameborder="0" allowfullscreen></iframe>

比較的簡単な修正で済んで助かった!

最後に

いかがでしたでしょうか。知識の浅さを露呈してしまい誠に遺憾ではございますが、どなたかのお役に立てれば光栄に存じます。

最後までお付き合いくださり、ありがとうございました。


LIGでは、エンジニアを絶賛募集中!
http://liginc.co.jp/recruit/mid_career

この記事を書いた人

榊原
榊原 外部ライター 鎌倉
生まれも育ちも横浜のホエールズ狂。DB技術者・プログラマを経てWeb技術者。デザイナの相棒と"webや"をやっています。[http://web-ya.works/]|[最近のヒット!(過去のブログ)]|[webや]

こちらもおすすめ

jQuery 仕事の現場でサッと使える! デザイン教科書 (Webデザイナー養成講座)

jQuery 仕事の現場でサッと使える! デザイン教科書 (Webデザイナー養成講座)

  • 著者吉本 集
  • 価格¥ 3,002(2015/11/05 15:42時点)
  • 出版日2015/04/21
  • 商品ランキング90,353位
  • 大型本336ページ
  • ISBN-104774172731
  • ISBN-139784774172736
  • 出版社技術評論社