jQueryを使った一定以上スクロールすると上に固定される横メニュー
最近、上部に固定された横メニューをよく見かけます。最初から一番上にあるものだと最初から「position:fixed」で問題ないと思いますが、最初は一番上にはなく、メニューがページの最上部までスクロールされた時点で固定されるものだとちょっと工夫が必要です。
サンプルページを用意しましたのでご確認ください。以前書いた「jQueryとCSS3を使ったアコーディオンメニューを詳しく説明します|Webpark」という記事のサンプルページを使い回してメニューを付けてみました。
今回はそんな横メニューをできるだけ親切に解説してみます。
今回のメインはjQueryで固定するところなのですが、一応今回のサンプルで使用したHTMLとCSSも解説します。
HTML
よくあるタイプの普通のリストメニューです。
<div id="menu-wrap"> <ul id="menu"> <li><a href="#">メニュー</a></li> <li><a href="#">メニュー</a></li> <li><a href="#">メニュー</a></li> <li><a href="#">メニュー</a></li> <li><a href="#">メニュー</a></li> </ul> </div>
左右画面いっぱいにするためdivで囲っています。
CSS
続いてCSSです。こちらもよく見かける感じですね。
#menu-wrap { width: 100%; height: 40px; box-shadow: 0 1px 10px #333; background: #2f2b3f; } #menu { list-style-type: none; width: 960px; margin: 0px auto 0px; padding: 0; } #menu li { width: 20%; float: left; margin: 0; padding: 0; text-align: center; } #menu li a { display: block; width : 100%; padding: 13px 0; color: #fff; font-size: 14px; font-weight: bold; line-height: 1; text-decoration: none; } #menu li a:hover { background: #272435; } .fixed{ position: fixed; top: 0px; left: 0px z-index: 9999; }
復習も兼ねて個別に解説していきます。
CSSを個別に解説
では、コード、解説の順で説明していきます。
#menu-wrap { width: 100%; height: 40px; box-shadow: 0 1px 10px #333; background: #2f2b3f; }
これで左右いっぱいに表示されるようにしています。中の要素にfloat(回り込み)が使われていて、clear(回り込み解除)されていませんので、高さを指定しないとこのボックスの高さ0になってしまいます。clearfixを使っても大丈夫です。高さの計算方法は後で説明します。
#menu { list-style-type: none; width: 960px; margin: 0px auto; padding: 0; }
メニュー全体の設定です。「margin: 0px auto;」で画面中央に表示されます。
#menu li { width: 20%; float: left; padding: 0; margin: 0; padding: 0; text-align: center; }
今回は5つのメニューがありますので「width: 20%;」に、横並びにするために「float: left;」を指定します。marginやpaddingで左右に間隔を取ると、うまく収まらないので気をつけてください。
#menu li a { display: block; width : 100%; padding: 13px 0; color: #fff; font-size: 14px; font-weight: bold; line-height: 1; text-decoration: none; }
先ほど指定したリスト内全体をクリックできるようにしています。「line-height: 1;」をしておくと、全体の高さを計算しやすくなります。ピクセル単位で指定しても大丈夫ですが、パーセント指定はやめたほうが無難です。
この場合、paddingが上下に13px、フォントが14pxの高さが40pxになります。#menu-wrapで指定した高さですね。
#menu li a:hover { background: #272435; }
マウスを乗せたときの色になります。
.fixed{ position: fixed; top: 0px; z-index: 9999; }
これは、スクロールした適応するスタイルです。これで画面の一番上に固定されます。どこよりも優先して表示したいのでz-indexで大きい数字を指定します。
jQuery
では今回のメインのjQueryの説明をします。
まず、jQueryを読み込みます。一番人気のGoogleのSDNを使います。
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
続いてjQueryの設定です。
$(function(){ var box = $("#menu-wrap"); var boxTop = box.offset().top; $(window).scroll(function () { if($(window).scrollTop() >= boxTop) { box.addClass("fixed"); $("body").css("margin-top","40px"); } else { box.removeClass("fixed"); $("body").css("margin-top","0px"); } }); });
var box = $("#menu-wrap");
menu-wrapというID名が付いた要素を変数「box」とします。今回のサンプルでは全体を囲むdiv要素になります。
var boxTop = box.offset().top;
ページが表示された時点での「box」が表示されている位置(上側)を変数「boxTop」とします。
$(window).scroll(function () {
スクロールしたときの動作を以下に書くことになります。
if($(window).scrollTop() >= boxTop) {
メニュー上部の位置(boxTop)と同じかそれ以上にスクロールした際の動作を以下に書きます。分かりにくいので違った言い方とすると、下へスクロールしていってメニューが画面の上に達したとき以降の動作です。
box.addClass("fixed");
変数「box」にクラス名「fixed」のスタイルを適用します。メニュー全体に「position:fixed」が適用され、最上部に固定されます。
$("body").css("margin-top","40px");
メニュー全体を表す変数「box」にクラス名「fixed」のスタイルを適用すると、メニューの高さ分だけ下にある要素が上に詰まります。メニューの高さ40px分上に詰まるため、bodyの上部にメニューの高さと同じ40pxの間隔を取って何もなかったかのようにします。これでスムーズに固定されます。
} else {
上へスクロールして、固定しなくてもメニューが見える状態になったときの動作を以下に書きます。
box.removeClass("fixed");
クラス名fixedのスタイルを外して元の状態に戻します。
$("body").css("margin-top","0px");
bodyの上部に取っていた間隔をなくします。
ということでjQueryの解説でした。言葉でいうと難しいので、サンプルを見ながらイメージしていただければと思います。
まとめ
ということで、一定以上スクロールすると固定される横メニューをjQueryを使って作ってみました。
今回は通常の横メニューにしましたが、ソーシャル系のアイコン、ホームボタン、検索窓なんかを設置しているサイトもよく見かけますね。
ずっと見えているということで、常にスペースを使うことになります。大きすぎて邪魔になってもいけませんし、大きい上にあまり必要のないものでしたらマイナス効果だと思います。
ユーザーにとって役立つものを設置できていれば非常に便利な機能ですので、一度検討してみてはどうでしょうか。
どこを改善すれば宜しいでしょうか?