WEBOPIXEL

jQuery製クールに開く横型サブナビゲーション

Posted: 2011.09.29 / Category: javascript / Tag: ,

スライドして開く横型のサブナビゲーションを作ってみました。しかし、あまり柔軟性がよろしくないので局地的にしか使えなませが、もし興味あったら、、、。

Sponsored Link

DEMO

デモはこちら。Chrome、Firefox、Opera、Safariの新しめのやつと、一応IE6でも動きます。

demo

※2012.01.28 – Firefox9/IE9で表示が乱れていた部分を修正

やってること

スライドナビゲーション概略図

サブナビゲーションは普通に「#nav ul li」にマウスオーバーして開きます。
「#navbg」は「#nav」からは独立していて、「#nav ul」にマウスオーバーすると「#nav ul li」の位置までスライドして開きます。

html+css

htmlはリストの中にリストが入ってます。サブナビゲーションがある場合はだいたいこんな感じですよね。

html

	<div id="nav">
	<ul class="clearfix">
		<li><a href="#">HOME</a></li>
		<li>
			<a href="#">ABOUT</a>
			<ul>
				<li><a href="#">ABOUT01</a></li>
				<li><a href="#">ABOUT02</a></li>
				<li><a href="#">ABOUT03</a></li>
				<li><a href="#">ABOUT04</a></li>
			</ul>
		</li>
		<li>
			<a href="#">BLOG</a>
			<ul>
				<li><a href="#">BLOG01</a></li>
				<li><a href="#">BLOG02</a></li>
				<li><a href="#">BLOG03</a></li>
			</ul>
		</li>
		・・・・
	</ul>
	<!--  /#nav--></div>
	

cssはムダなところが多いかもしれませんが、こんな感じにするとナビゲーションが横並びになります。

css

	#nav {
		padding: 0 10px;
		font-size: 116%;
		color: #2C342D;
		border-bottom: solid 1px #2C342D;
		background: #EFF1EF;
	}
	#nav ul li {
		list-style: none;
		float: left;
		cursor: pointer;
	}
	#nav ul li a {
		font-weight: bold;
		text-decoration: none;
		color: #424F44;
		display: block;
		padding: 8px 20px;
	}
	#nav ul li a.over  {
		background: #D1D8D1;
	}
	#nav ul li ul  {
		position: absolute;
		z-index: 1;
	}
	#nav ul li ul li  {
		position: absolute;
		width: auto;
		cursor: pointer;
		font-size: 80%;
	}
	#nav ul li ul li a {
	padding: 11px 16px;
	background: transparent;
	white-space: nowrap;
	color: #fff;
	}
	#nav ul li ul li a:hover {
		background: #373C37;
	}
	#navbg {
		background: #6B726B;
		position: absolute;
		width: 0px;
	}
	

「#navbg」はhtmlにはないですが、サブナビゲーションのバックの部分で、あまり意味のない部分ですのでjQueryで配置します。

jQueryの部分

最初にメイン・サブナビゲーションの配置の設定を行います。

	var nav = $('#nav');
	//(メインメニュー)ulをliの合計のwidthにする
	var ulWidth = 0;
	$('>ul>li', nav).each(function (i) {
		ulWidth += $(this).outerWidth(true);
	});
	$('>ul', nav).css('width', ulWidth+'px');
	//サブメニューのwidth取得とUIの設定
	var subWidthArray = new Array();
	$('>ul>li', nav).each(function (i) {
		var tempNum = 0;
		if($('>ul',this).length == 1) {
			$('>ul>li',this).each(function () {
				$(this).css('left', tempNum + 'px');
				tempNum += $(this).outerWidth(true);
			});
			$('>ul',this).css('width', tempNum + 'px');
		} else {
			subWidthArray[i] = 0;
		}
		subWidthArray[i] = tempNum;
	});
		
2~7行目
サブナビゲーションのwidthを一つ一つ取得して、メインナビゲーション全体のwidthに割り当ててます。
ulはブロック要素なのでそのままだと横画面一杯に広がってますので、マウスオーバーしたときにあまりよろしくありません。
ただ、横型のナビゲーションだとボタンを画像にすることが多いので、その場合はcssで指定した方が早いですね。
9~21行目
サブナビゲーションでも同じようにwidthを取得してます。
サブメニューは絶対配置なのでwidthを取得した分だけleftで右にずらします。
(2012.01修正)

その他初期設定とかです。

		//サブナビゲーションに追尾するやつを配置
		nav.append('<div id="navbg"></div>');
		var navbg = $('#navbg');
		//navbgの初期位置
		var homeLeft = nav.position().left;
		//サブナビゲーションがマウスオーバー状態か
		var subNavFlug = false;
		//#navbgの高さをサブナビゲーションと同じにする
		navbg
			.height($('ul li ul li', nav).height())
			.css({
				'top': $('ul li ul', nav).position().top,
				'left': $(nav).position().left
			});
		//サブナビゲーションを非表示
		$('ul ul', nav).css('display', 'none');
		

メインulにマウスオーバーしたら

ここからマウスオーバーの処理です。
メインのulのマウスインの設定はありませんが、アウトしたときかつ「subNavFlug」が「false」のときに初期地点に戻り、横幅を0にします。

		$('ul', nav).hover(
		function() {},
		function() {
			if (subNavFlug == false) {
				navbg.animate({
					'left' : homeLeft,
					'width': 0
				}, 300);
			}
		});
		

メインliにマウスオーバーしたら

サブナビゲーションの開閉はliのマウスオーバーで設定します。

		//メインナビゲーションマウスオーバーでサブナビゲーション開く
		$('>ul>li',nav).hover( function() {
			$('>a',this).addClass('over');
			var currntNum = $(this).index();
			var currentUl = $('ul', this);
			currentUl
				.show()
				.css('opacity', 0);
			//X座標取得
			var posX = $(this).position().left;
			currentUl.css('left', posX);
			//navbgをサブナビゲーションの位置に移動
			if(subWidthArray[currntNum]) {
				navbg.animate({'left' : posX, 'width': subWidthArray[currntNum]}, 300, function(){
					currentUl.css({'opacity': 1});
				});
			} else {
				navbg.animate({'left' : homeLeft, 'width': subWidthArray[currntNum]}, 300);
			}
		},
		function() {
			$('>a',this).removeClass('over');
			$('ul', this).hide();
		});
		

サブナビゲーション(currentUl)はマウスオーバー後すぐに表示(show)すると「#bgnav」がない状態で表示されてしまいますので、すぐに透明度(opacity)を0にしてアニメーション後に透明度を1にします。

サブナビゲーションのマウスオーバーでフラグON

最後にフラグ(subNavFlug)の切り替えを行ってます。

		//サブナビゲーションマウスオーバーでフラグON
		$('>ul>li>ul',nav).hover( function() {
			subNavFlug = true;
		},
		function() {
			subNavFlug = false;
		});
		
最終的なコードです。
ソースコード

COMMENTS

tezutaku 2011-11-05 18:03 

このメニューをサイトで利用させて頂くことは可能でしょうか。

webOpixel 2011-11-05 22:11 

自由に使って頂いて大丈夫です。
必須ではないですが、どのサイトで使ったか教えて頂けると嬉しいです。

tezutaku 2011-11-06 11:13 

ありがとうございます。了解しました。実装完了して公開したら連絡いたします。

tezutaku 2012-01-26 22:57 

MacOS X版のFirefox9やIE8でメインメニューやサブメニューが折り返してしまうことがあります。
対策はあるでしょうか?
var ulWidth = 50; とかvar tempNum = 20;で初期値を設定したら折り返さないようになりましたが、
これはまずいでしょうか?
safariやChromeでは問題ないです。

tezutaku 2012-01-26 23:12 

var tempNum = 20;としましたが、これはまずかったです。サブメニューのないところにも表示されます。
$(‘>ul’,this).css(‘width’, tempNum + 20 + ‘px’);としたらいけましたが
超対処療法ですが・・・

tezutaku 2012-01-27 11:04 

連投すみません。

hoge
hogehoge

のようにliにclassを設定した場合、class名にentryという文字列を設定すると、
なぜかnavbgのheightが違ってきます。

webOpixel 2012-01-28 15:51 

tezutakuさんありがとうございます。
サブメニューが崩れている部分はfloatで配置していたのがよくなかったみたいです。
(何か意図があったのかもしれませんが思い出せません……)
とりあえず絶対配置にしたものをアップしました。

heightの部分は
$(‘ul li ul li’, nav).height()
としてみてください。
もしくは他に「entry」というクラスが設定してあるということはありませんか?

tezutaku 2012-02-01 21:05 

対応いただきありがとうございました。
メインメニューが折り返すのでフォント指定(Arial, Helvetica, sans-serif;)を#navにしたら解消できました。
entryに関してはa href=”#a01″ class=”entry”のように指定すると高さがおかしくなります。
謎です。とりあえず別のclass名をつければ大丈夫なのでそれで利用させていただきます。

tezutaku 2012-02-04 12:18 

何度もすみません。
サブメニューの名称にMenu nameのようにスペースが入っていると横サイズがおかしくなります。
 でスペースを入れると大丈夫です。
あと、2バイト文字を使うと同様に横サイズの認識がおかしいです。
デモページのソースで試しました。

webOpixel 2012-02-06 11:19 

中途半端なものをアップしてしまいすみません。
「#nav ul li ul li a」のcssに「white-space: nowrap;」を追加してみてください。
サンプルの方も修正いたしました。

アシベ 2014-06-03 10:41 

ソースコードの
//サブナビゲーションに追尾するやつを配置
nav.append(”);
を記述した後に
var navbg = $(‘#navbg’);
に代入すると一緒に利用しているjquery.bxslider.jsプラグインと共に動かなくなってしまいます。
とても困っています。何か解決方法はありませんか?

webOpixel 2014-06-10 09:26 

例えば同じ要素を選択している場合は動かなくなる可能性はありますが、そういうことではないんですかね?

アシベ 2014-06-11 18:47 

webOpixel様、ご回答ありがとうございます。
あれから原因を調べてみましたがつい先ほどわかりました。
お互いのJqueryはちゃんと機能しているのですが、bxsliderのCSSの数箇所の記述が矛盾を出していることが分かり解決することができました。
今後もこのクールなメニューのようなすばらしい作品を楽しみにしております。
ありがとうございました。

LEAVE A REPLY

コードを書く場合は<pre>で囲んでください。