[jQuery]レスポンシブに対応したナビゲーションを作ってみました。

ウィンドウの幅に応じて、動作とデザインが切り替わるナビゲーションを作ってみました。ウィンドウ幅が広ければヘッダーに横一列で表示し、スマフォなどの場合はボタンで操作でナビゲーションが開閉します。

html

<header class="header">
	<h1>sample-responsive_menu</h1>
	<button class="menu_btn none">メニュー</button>
	<nav class="navigation">
		<ul>
			<li>メニュー1</li>
			<li>メニュー2</li>
			<li>メニュー3</li>
			<li>メニュー4</li>
			<li>メニュー5</li>
		</ul>
	</nav>
</header>

PCなどではヘッダーに横一列に、スマフォでは縦に並べて必要なときにボタンで開閉させる、オーソドックスなナビゲーション。

css

.none{
	display: none;
}

.menu_btn{
	cursor: pointer;
	padding: 10px;
}

.navigation li{
	list-style: none;
}

@media screen and (min-width: 641px) {
	.navigation li{
		float: left;
		margin: 10px;
	}
}

jQuery

jQuery(function() {


	var $btn = jQuery('.menu_btn');
	var $nav = jQuery('.navigation');

	/*
	 * ブラウザのウィンドウ幅を取得してメニューボタンとナビゲーションの表示/非表示を切り替え
	 */

	jQuery(window).resize(function(){

		var w = jQuery(window).width(); //ブラウザの幅を取得
		var x = 768; //ブレイクポイントを設定

		if (w <= x) { // ウィンドウサイズが768px以下

			jQuery($btn).removeClass('none');
			jQuery($nav).addClass('none');

			} else { //ウィンドウサイズが768以上
				jQuery($btn).addClass('none').text('メニュー'); //非表示・文字をメニューにする
				jQuery($nav).removeClass('none').removeAttr('style'); //表示・styleを初期化する
			}

	});

	/*
	 * クリックイベントによるスライドダウン/アップ
	 */

	jQuery($btn).on('click',(function(){

		if (jQuery($nav).css('display')=='none'){
			jQuery($nav).slideDown('slow');
			jQuery($btn).text('メニューを閉じる');
		} else {
			jQuery($nav).slideUp('fast');
			jQuery($btn).text('メニュー');
		}

		})
	);


});

demo

開閉ボタンとナビゲーションは、ウィンドウ幅に応じて.noneを付けたり取ったりしてdislplayの状態をコントロールします。ナビゲーションが閉じているときはボタンの文字が「メニュー」、開いているときは「メニューを閉じる」になります。

PC閲覧時にウィンドウ幅をリサイズした場合も考慮していて、ウィンドウ640px以下にしてナビゲーションを開いた後、ウィンドウサイズを641px以上にした場合、ナビゲーションはいったん初期化。非表示になります。ボタンの文字もメニューに戻ります。

高機能なjQueryプラグインがいろいろあるので使ってもいいのですが、自分で作ったほうがカスタマイズが簡単だったり、設置が手軽だったりするかと。

なにより自分で作ってみるといろいろと勉強になります。

※なお、jQuery(window).resize(function(){/*何らかの処理*/});という記述でウィンドウ幅を取得しているのですが、リサイズし続ける間中取得し続けるので、発火する処理によってはブラウザに負荷がかかるようです。注意が必要かと思います。

参考:[jQuery] ウインドウのリサイズ操作が終わった時にだけ処理を実行する | CreativeStyle

[jQuery]タップで開閉するメニューをif文で作る。

マウスをhoverさせて表示/非表示を切り替えるメニュー(ドロップダウンメニューなど)はよくありますが、iPadなどタッチデバイスではhoverは動作しません。

なので、タッチデバイス向けにタップすると表示され、もう一度タップすると非表示になるメニューを作成してみました。

あまり洗練された動きではないですが、jQueryの勉強として公開してみます。

サンプルコード

<!DOCTYPE html>
<html lang="jp">
<head>
	<meta charset="UTF-8">
	<title>example</title>
	<script src="http://code.jquery.com/jquery-2.1.1.min.js"></script>

	<style type="text/css">
	
		.menu{
			float: left;
			margin-left: 30px;
		}

		li{
			list-style: none;
		}

		button{
			padding: 5px 30px;
		}

		ul{
			padding: 0;
			display: none;
		}

	</style>

    <script type="text/javascript">

		jQuery(function() {

			jQuery('.menu').on('click', function(){
				var content = jQuery('ul',this);
				if(jQuery(content).css('display')=='none'){ //contentのdisplayがnoneの場合
					jQuery(content).css('display','block');
				}else{//contentのdisplayがnoneではない場合
					jQuery(content).css('display','none');
				}

			});

		});

    </script>

</head>
<body>
<div>
	
	<div class="menu">
		<button type="button">ボタン1</button>
		<ul>
			<li>メニュー1</li>
			<li>メニュー2</li>
			<li>メニュー3</li>
			<li>メニュー4</li>
			<li>メニュー5</li>
		</ul>
	</div>
	<div class="menu">
		<button type="button">ボタン2</button>
		<ul>
		<li>メニュー6</li>
		<li>メニュー7</li>
		<li>メニュー8</li>
		<li>メニュー9</li>
		<li>メニュー10</li>
		</ul>
	</div>
	<div class="menu">
		<button type="button">ボタン3</button>
		<ul>
		<li>メニュー11</li>
		<li>メニュー12</li>
		<li>メニュー13</li>
		<li>メニュー14</li>
		<li>メニュー15</li>
		</ul>
	</div>

</ul>
</body>
</html>

demo

コードをおさらい

jQeryの部分を抽出してひとつひとつ見ていきます。

clickイベントをon()を使って設定する。

サンプルコードでは、li要素をメニュー項目として、ul要素のdisplayのblock/noneを切り替えるという動作をさせます。

jQuery('.menu').on('click', function(){

とすることで、.menuに対してclickイベントを設定。
クリックした.menu直下のul要素だけを対象にするためにthisを使って以下のように

var content = jQuery('ul',this);

値を取得し、変数に入れて次の処理で使います。

ここまでの2行で開閉させたいul要素を絞り込むところまで出来ました。
次の工程では実際に開閉させるための処理を作っていきます。

if分岐でdisplayをコントロールする

ul要素のdisplayが「noneであればblock」にして表示、「blockならnone」にして非表示といったif分岐を作ります。

if(jQuery(content).css('display')=='none'){
//〜

== は「左右の値が同じ」ならtrueを返す演算子です。
「content(クリックした.menuの子要素のul要素)」のdisplayの値が「none」と同じかどうか比較しています。
同じ場合、つまりdislay:noneならば次の処理に進みます。

jQuery(content).css('display','block');

display:noneをblockに変えてul要素を表示します。
noneと同じではなかった場合(ul要素のdisplayがblockだった場合)、falseが返されてこの処理はスキップ。次の処理に進みます。

}else{
	jQuery(content).css('display','none');
}

displayをblockに変えます。開閉することが目的なので、メニューが閉じている状態でも開いている状態でも対応できています。
以上のスクリプトをタッチデバイスの時のみ読み込むようにするといいと思います。
WordPressであれば、is_mobile()とかですね。

以上で完了です。
間違いがあれば指摘いただけると幸いです。

[jQuery].each()とthisを使って要素ごとに繰り返し処理を行う。

繰り返し処理のサンプルコードを作ってみました。
span要素とa要素を含むli要素があったとして、li要素ごとにa要素の中にspan要素を移動させる、というような動作をさせます。繰り返しさせるために.each()を使います。

jQuery

jQuery(function(){

	jQuery('li').each(function(){
		var url = jQuery('a',this); //liの子要素のa要素を取得し、変数にセットする。
		jQuery('span',this).prependTo(url); //liの子要素のspan要素を変数urlの要素の内側先頭にに移動する。
	});

});

html

<ul>
	<li>
		<span>hoge1</span>
		<a href="">:リンク</a>
	</li>
	<li>
		<span>hoge2</span>
		<a href="">:リンク</a>
	</li>
	<li>
		<span>hoge3</span>
		<a href="">:リンク</a>
	</li>
	<li>
		<span>hoge4</span>
		<a href="">:リンク</a>
	</li>
	<li>
		<span>hoge5</span>
		<a href="">:リンク</a>
	</li>
	<li>
		<span>hoge6</span>
		<a href="">:リンク</a>
	</li>
</ul>

実行結果(html)


<ul>
	<li>
		<a href=""><span>hoge1</span>:リンク</a>
	</li>
	<li>
		<a href=""><span>hoge2</span>:リンク</a>
	</li>
	<li>
		<a href=""><span>hoge3</span>:リンク</a>
	</li>
	<li>
		<a href=""><span>hoge4</span>:リンク</a>
	</li>
	<li>
		<a href=""><span>hoge5</span>:リンク</a>
	</li>
	<li>
		<a href=""><span>hoge6</span>:リンク</a>
	</li>
</ul>

demo

実際の動作は以下のデモページよりご覧いただけます。
eachデモ

まとめ

jQuery(‘a’,this)とすることで”li要素の子要素のa”を取得し、それを変数”url”に入れる。
次にjQuery(‘span’,this)→li要素の子要素のspanを指定して、.prependTo(url)→変数urlに入ってるaの中に入れるよ。でもって.each()でくくってるからli要素無くなるまで繰り返すよ、というような理解でいいと思います。

参考URL

jQuery の $().each() で個別処理(ループ) | バシャログ。

【jQuery】要素を指定するセレクタの使い方 まとめ | Web制作会社スタイル

[jQuery]find()メソッドで偶数(奇数)の要素を取得するサンプル

以下の様に複数のul要素があるhtmlの構成で、それぞれのulごとに内包するli要素の偶数番目(0から数えて)にclassを付けたかったので、jQueryのevenセレクタを使ってやってみました。

サンプルコード

html

<ul>
	<li>1</li>
	<li>2</li>
	<li>3</li>
</ul>
<ul>
	<li>4</li>
	<li>5</li>
</ul>
<ul>
	<li>6</li>
	<li>7</li>
	<li>8</li>
	<li>9</li>
	<li>10</li>
</ul>
<ul>
	<li>11</li>
</ul>

css

.red{
	color: red;
}

jQuery

jQuery(function(){
	jQuery('ul').find('li:even').addClass('red');
});

以下に挙げる失敗例のように、findセレクタ無しだとul要素ごとじゃなく、全部のli要素を合算した上で偶数にclassを付けてしまいます。

findセレクタを使うと意図どおりにclassがつきました。
find()は指定した要素の「子孫」要素でセレクタにマッチする要素を選択することができます。

jQuery失敗例

jQuery(function(){
	jQuery('ul li:even').addClass('red');
});

※ちなみに、0から数えて奇数番目にclassを付けたい場合はoddセレクタを使います。

demo

※上記コードの実行結果を閲覧できます。
demo-find.html

参考:jQuery リファレンス:find

jQueryプラグイン「MaxImage 2」を使ってサイトの背景に写真をフルスクリーンで表示させる方法

jQueryプラグイン「Maximage2」を使うと、ブラウザの幅と高さいっぱいに一枚の画像を背景として表示させることができます。

(1)jquery.maximage.jsとjquery.maximage.cssをakv2/MaxImageよりダウンロードし、任意のディリクトリに設置して下さい。表示させたい画像もご自身でご用意して下さい。

(2)以下のコードでhtmlを作成すると、ブラウザの幅と高さいっぱいに一枚の画像を背景として表示させることができます。


<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <script src='http://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.js'></script>
    <script type='text/javascript' src='jquery.maximage.js'></script>
    <link rel="stylesheet" type="text/css" href="jquery.maximage.css" />
    <script type="text/javascript">
        jQuery(function(){
            jQuery('#maximage').maximage();
        });
    </script>
</head>
<body>
    <div id="maximage">
        <img src="sample.jpg" alt="sample" /><!--背景として利用する画像-->
    </div>
</body>
</html>

Demo

jQueryプラグイン:スクロール後に指定したナビゲーション等を固定する「STICKYMOJO.JS」を試してみました。

PHPSPOT開発日誌さんで紹介されていたjQueryプラグイン「STICKYMOJO.JS」を試してみました。
サイドに配置したナビゲーションなどのコンテンツを、ブラウザ上端までスクロールしたら固定配置に切り替えるプラグインです。

stickyMojo

head要素に以下のように記述し、

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<script src="js/stickyMojo.js"></script> <!--stickyMojo.jsをダウンロードして任意のフォルダに設置する。-->
<script type="text/javascript">
$function(){
     $('#sidebar').stickyMojo({footerID: '#footer', contentID: '#main'});
});
</script>

以下のような構成のhtmlレイアウトで動作するようです。

<div id="wrapper">
 
  <div id="sidebar">
    <p>sidebar</p>
  </div>
 
  <div id="main">
    <p>main</p>
  </div>
 
  <div id="footer">
    Footer
  </div>
 
</div>

#sidebar、#footer、#mainなどのセレクタは任意のものに変えてもよいようです。

参考にさせていただいたサイト

スクロールしたときにサイドバーのパーツをjQueryで止める方法: 小粋空間

[JS]複数の指定した範囲ごとにスクロールに追従するパネルを設置するスクリプト -jQuery Stick ‘em | コリス