CSS3とjQueryで作る「開閉に合わせて×ボタンに変化させる」ハンバーガーメニュー

最近流行っている「開閉に合わせて×ボタンに変化させる」ハンバーガーメニューをCSS3とjQueryを使って再現してみました。

以前作成した「jQueryとCSS3でマテリアルデザインのハンバーガーメニュー」とソースが似ています。

スポンサードリンク

デモ・ソース

これだけじゃ「そもそも何だよそれ」って話だと思うので、デモを用意しました。百聞は一見に鹿ずって言いますもんね。

See the Pen Hamburger Navigation Menu by tokumewi (@tokumewi) on CodePen.

右上にある三本の線(ハンバーガーメニュー)をクリックすると、線が×の形に変化しながらグローバルナビゲーションが横からスライドして出てきます。

上手く見れない人のためにgifアニメにしてみました。

menu animation

IE9ではCSSのtransitionに対応していないので、押した瞬間に形が変化します。

html


<div id="wrap">
<header>
    <div class="inner">
        <h1>SITE LOGO</h1>
        <p class="navBtn">
            <span></span>
            <span></span>
            <span></span>
        </p>
        <nav role='navigation'>
            <ul>
                <li><a href="#">Home</a></li>
                <li><a href="#">About</a></li>
                <li><a href="#">Product</a></li>
                <li><a href="#">Works</a></li>
                <li><a href="#">Links</a></li>
                <li><a href="#">Contact Us</a></li>
            </ul>
        </nav>
    <!-- /.inner --></div>
</header>

<div id="contents">
    <p>コンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツ</p>
    <p>コンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツ</p>
        <p>コンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツ</p>
        <p>コンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツコンテンツ</p>
    <!-- /#contents --></div>
<!-- /#wrap --></div>

CSS


html, body, div, span, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
abbr, address, cite, code,
del, dfn, em, img, ins, kbd, q, samp,
small, strong, sub, sup, var,
b, i,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td,
article, aside, dialog, figure, footer, header,
hgroup, menu, nav, section,
time, mark, audio, video {
        -webkit-transition: 0.3s ease-in-out;
        -moz-transition: 0.3s ease-in-out;
        transition: 0.3s ease-in-out;
}

body {
    font-family: 'Questrial', Verdana, "ヒラギノ角ゴ ProN W3", "Hiragino Kaku Gothic ProN", "メイリオ", Meiryo, sans-serif;
}

.fixed {
    position:fixed;
    top:0;
    left:0;
    width:100%;
}

h1 {
    font-size:1.5em;
    font-weight:bold;
}

/* オーバーレイ */
.overlay {
        position: fixed;
        top: 0;
        left: 0;
        display: none;
        width: 100%;
        height: 100%;
        background: #000;
        opacity: 0.7;
        filter: alpha(opacity=70);
        -ms-filter: "alpha(opacity=70)";
        z-index: 999;
}

/* ヘッダー */
header  {
    position:fixed;
    top:0;
    left:0;
    width:100%;
    background:#fff;
    box-shadow: 0 2px 5px rgba(0,0,0,0.26);
    z-index:9999;
    -webkit-user-select:none;
    -moz-user-select:none;
    user-select:none;
}
header .inner {
    position:relative;
    padding:1.5em;
    -webkit-box-sizing:border-box;
    -moz-box-sizing:border-box;
    box-sizing:border-box;
}

/* ナビゲーション */
header nav {
        overflow:auto;
        position: fixed;
        top: 0;
        right: -70%;
        width: 70%;
        max-width:320px;
        height: 100%;
        background: #fff;
        opacity: 0;
        z-index:9999;
}
/* ナビゲーション:アクティブ時 */
header.navOpen nav {
        opacity: 1;
        right: 0;
}
header nav ul {
    border-top:1px solid #ccc;
}
header nav ul li {
    border-bottom:1px solid #ccc;
}
header nav ul li a {
    position:relative;
    display:block;
    padding:1.5em;
    color:#999;
    text-decoration:none;
}
header nav ul li a:hover {
    background:#f2f2f2;
}
header nav ul li a:before {
  position: absolute;
  top: 50%;
  right: 1.5em;
  display: inline-block;
  content: "";
  width: 7px;
  height: 7px;
  margin-top: -4px;
  margin-right: -4px;
  vertical-align: middle;
    border-top: 3px solid #E60012;
  border-right: 3px solid #E60012;
  -webkit-transform: rotate(45deg);
  transform: rotate(45deg);
  -ms-transform: rotate(45deg);
}

/* ナビゲーションアイコン */
header .navBtn {
        display: block;
        width: 30px;
        position: absolute;
        top: 24px;
        right: 15px;
        cursor: pointer;
}
header .navBtn span {
        display: block;
        height: 4px;
        width: 100%;
        background: #E60012;
        border-radius: 2px;
        -webkit-transition: all .5s ease-in-out;
        -moz-transition: all .5s ease-in-out;
        transition: all .5s ease-in-out;
}
header .navBtn span:nth-of-type(2),
header .navBtn span:nth-of-type(3) {
        margin-top: 5px;
}
/* ナビゲーションアイコン:アクティブ */
header.navOpen .navBtn span:nth-of-type(1) {
        -webkit-transform: translateY(9px) translateX(0) rotate(45deg);
        -ms-transform: translateY(9px) translateX(0) rotate(45deg);
        transform: translateY(9px) translateX(0) rotate(45deg);
}
header.navOpen .navBtn span:nth-of-type(2) {
        margin-top: 5px;
        opacity: 0;
        -webkit-transform: translateY(9px);
        -ms-transform: translateY(9px);
        transform: translateY(9px);
}
header.navOpen .navBtn span:nth-of-type(3) {
        -webkit-transform: translateY(-9px) translateX(0) rotate(-45deg);
        -ms-transform: translateY(-9px) translateX(0) rotate(-45deg);
        transform: translateY(-9px) translateX(0) rotate(-45deg);
}

#contents {
    margin-top:80px;
    padding:1em 1.5em;
    line-height:1.5;
}
#contents p {
    margin-bottom:1em;
}

jQuery


// =========================================
// ナビゲーションアイコン
// =========================================

// オーバーレイ作成
$('#contents').prepend('<div class="overlay"></div>');

// アイコンをクリックしたら
$('.navBtn').click(function() {
        $('header').toggleClass('navOpen'); // class付与/削除
        $('#wrap').toggleClass('fixed'); // コンテンツを固定/解除
        $('.overlay').toggle(); // オーバーレイ表示/非表示

        // スマホナビゲーションがヘッダーに被らないようにする
        var headerH = $('header').outerHeight();
        if ($('header').hasClass('navOpen')) {
                $('header nav').css('marginTop', headerH + 'px'); //ヘッダーの高さ分マージンを付ける
        }
});

// オーバーレイをクリックしたら
$('.overlay').click(function() {
        $(this).fadeOut(300); // オーバーレイ非表示
        $('header').removeClass('navOpen'); // class削除
        $('#wrap').removeClass('fixed'); // 固定解除
});

すごく適当な解説

やっていることはそこまで難しくなく、動作は主にCSS3のtransitionで、jQueryはclassを付けたり外したりしているだけです。あとはオーバーレイの動きを「ナビゲーションの開閉に応じて表示/非表示を切り替える」だけで作れます。

ナビゲーションの動きは、positionで右上に配置しておいてボタンが押されてclassが付与されたときだけright:-70%;の値を0にしています。


/* ナビゲーション */
header nav {
        overflow:auto;
        position: fixed;
        top: 0;
        right: -70%;
        width: 70%;
        max-width:320px;
        height: 100%;
        background: #fff;
        opacity: 0;
        z-index:9999;
}
/* ナビゲーション:アクティブ時 */
header.navOpen nav {
        opacity: 1;
        right: 0;
}

ハンバーガーアイコンもコードが長いだけでやっていることは簡単です。3つあるに赤色のボーダーを付けて、2個め、3個めだけマージンを付けて間隔を空ける。

ナビゲーションがアクティブになったら、1つ目のボーダーを時計回りに45度傾けて9px下げる、3つ目はその逆で反時計回りに45度傾けて9px上げる、真ん中の線は9px下がりつつopacityで透明にします。


/* ナビゲーションアイコン */
header .navBtn {
        display: block;
        width: 30px;
        position: absolute;
        top: 24px;
        right: 15px;
        cursor: pointer;
}
header .navBtn span {
        display: block;
        height: 4px;
        width: 100%;
        background: #E60012;
        border-radius: 2px;
        -webkit-transition: all .5s ease-in-out;
        -moz-transition: all .5s ease-in-out;
        transition: all .5s ease-in-out;
}
header .navBtn span:nth-of-type(2),
header .navBtn span:nth-of-type(3) {
        margin-top: 5px;
}
/* ナビゲーションアイコン:アクティブ */
header.navOpen .navBtn span:nth-of-type(1) {
        -webkit-transform: translateY(9px) translateX(0) rotate(45deg);
        -ms-transform: translateY(9px) translateX(0) rotate(45deg);
        transform: translateY(9px) translateX(0) rotate(45deg);
}
header.navOpen .navBtn span:nth-of-type(2) {
        margin-top: 5px;
        opacity: 0;
        -webkit-transform: translateY(9px);
        -ms-transform: translateY(9px);
        transform: translateY(9px);
}
header.navOpen .navBtn span:nth-of-type(3) {
        -webkit-transform: translateY(-9px) translateX(0) rotate(-45deg);
        -ms-transform: translateY(-9px) translateX(0) rotate(-45deg);
        transform: translateY(-9px) translateX(0) rotate(-45deg);
}

レスポンシブデザインでスマホ時のみハンバーガーメニューに

このままではPCでもいちいちハンバーガーメニューを開かないといけないので、PCでは横1行のナビゲーション、タブレットでは横2行にして、スマホになったときだけ先ほどと同じハンバーガーメニューにするようなレスポンシブデザインの例を作成してみました。

See the Pen Hamburger Navigation Menu(Responsive) by tokumewi (@tokumewi) on CodePen.

右上のEdit On CODEPENをクリックすると別窓で開きます。またはこちらからどうぞ。

2015-06-16_132330
PCでは横1行のナビゲーション
2015-06-16_132347
タブレットでは横2行に

CSS


html, body, div, span, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
abbr, address, cite, code,
del, dfn, em, img, ins, kbd, q, samp,
small, strong, sub, sup, var,
b, i,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td,
article, aside, dialog, figure, footer, header,
hgroup, menu, nav, section,
time, mark, audio, video {
		-webkit-transition: 0.3s ease-in-out;
		-moz-transition: 0.3s ease-in-out;
		transition: 0.3s ease-in-out;
}

.clearfix:before,
.clearfix:after {
    content: " ";
    display: table;
}

.clearfix:after {
    clear: both;
}

.clearfix {
    *zoom: 1;
}

body {
	font-family: 'Questrial', Verdana, "ヒラギノ角ゴ ProN W3", "Hiragino Kaku Gothic ProN", "メイリオ", Meiryo, sans-serif;
}

.fixed {
	position:fixed;
	top:0;
	left:0;
	width:100%;
}

/* オーバーレイ */
.overlay {
		position: fixed;
		top: 0;
		left: 0;
		display: none;
		width: 100%;
		height: 100%;
		background: #000;
		opacity: 0.7;
		filter: alpha(opacity=70);
		-ms-filter: "alpha(opacity=70)";
		z-index: 999;
}

/* ヘッダー */
header  {
	position:fixed;
	top:0;
	left:0;
	width:100%;
	background:#fff;
	box-shadow: 0 2px 5px rgba(0,0,0,0.26);
	z-index:9999;
	-webkit-user-select:none;
	-moz-user-select:none;
	user-select:none;
}
header .inner {
	position:relative;
	max-width:1080px;
	margin:0 auto;
	padding:1.5em 0;
	-webkit-box-sizing:border-box;
	-moz-box-sizing:border-box;
	box-sizing:border-box;
}
header h1 {
	float:left;
	width:20%;
	margin-top: 1em;
	font-size:1.5em;
	font-weight:bold;
}

/* ナビゲーション */
header nav {
	float:right;
	width: 80%;
}
/* ナビゲーション:アクティブ時 */
header.navOpen nav {
		opacity: 1;
		right: 0;
}
header nav ul {
	width: 100%;
	border-top:1px solid #ccc;
}
header nav ul li {
	float:left;
	width: 16.6666%;
	border-bottom:1px solid #ccc;
}
header nav ul li a {
	position:relative;
	display:block;
	padding:1.5em;
	color:#999;
	text-decoration:none;
}
header nav ul li a:hover {
	background:#f2f2f2;
}
header nav ul li a:before {
  position: absolute;
  top: 50%;
  right: 1.5em;
  display: inline-block;
  content: "";
  width: 7px;
  height: 7px;
  margin-top: -4px;
  margin-right: -4px;
  vertical-align: middle;
	border-top: 3px solid #E60012;
  border-right: 3px solid #E60012;
  -webkit-transform: rotate(45deg);
  transform: rotate(45deg);
  -ms-transform: rotate(45deg);
}

/* ナビゲーションアイコン */
header .navBtn {
		display: none;
		width: 30px;
		position: absolute;
		top: 24px;
		right: 15px;
		cursor: pointer;
}
header .navBtn span {
		display: block;
		height: 4px;
		width: 100%;
		background: #E60012;
		border-radius: 2px;
		-webkit-transition: all .5s ease-in-out;
		-moz-transition: all .5s ease-in-out;
		transition: all .5s ease-in-out;
}
header .navBtn span:nth-of-type(2),
header .navBtn span:nth-of-type(3) {
		margin-top: 5px;
}
/* ナビゲーションアイコン:アクティブ */
header.navOpen .navBtn span:nth-of-type(1) {
		-webkit-transform: translateY(9px) translateX(0) rotate(45deg);
		-ms-transform: translateY(9px) translateX(0) rotate(45deg);
		transform: translateY(9px) translateX(0) rotate(45deg);
}
header.navOpen .navBtn span:nth-of-type(2) {
		margin-top: 5px;
		opacity: 0;
		-webkit-transform: translateY(9px);
		-ms-transform: translateY(9px);
		transform: translateY(9px);
}
header.navOpen .navBtn span:nth-of-type(3) {
		-webkit-transform: translateY(-9px) translateX(0) rotate(-45deg);
		-ms-transform: translateY(-9px) translateX(0) rotate(-45deg);
		transform: translateY(-9px) translateX(0) rotate(-45deg);
}

#contents {
	max-width: 1080px;
	margin:120px auto 0;
	padding:1em 1.5em;
	line-height:1.5;
}
#contents p {
	margin-bottom:1em;
}

/* レスポンシブ */
@media screen and (max-width:1080px){
	header .inner {
		padding: 1.5em;
	}
	header h1 {
		width: 30%;
		margin-top: 0em;
	}
	header nav {
		width:70%;
	}
	header nav ul li {
		width: 33.333%;
	}
	#contents {
		margin-top:180px;
	}
}
@media screen and (max-width:640px){
	header h1 {
		width: auto;
		margin-top: 0;
	}
	header .navBtn {
		display:block;
	}
	header nav {
			overflow:auto;
			position: fixed;
			top: 0;
			right: -70%;
			float:none;
			width: 70%;
			max-width:320px;
			height: 100%;
			background: #fff;
			opacity: 0;
			z-index:9999;
	}
	header nav ul li {
		float: none;
		width: auto;
	}
	#contents {
		margin-top:80px;
	}
}

jQuery


// ==============================================================
// ナビゲーションアイコン
// ==============================================================
// オーバーレイ作成
$('#contents').prepend('<div class="overlay"></div>');

// アイコンをクリックしたら
$('.navBtn').click(function() {
		$('header').toggleClass('navOpen'); // class付与/削除
		$('#wrap').toggleClass('fixed'); // コンテンツを固定/解除
		$('.overlay').toggle(); // オーバーレイ表示/非表示

		// スマホナビゲーションがヘッダーに被らないようにする
		var headerH = $('header').outerHeight();
		if ($('header').hasClass('navOpen')) {
				$('header nav').css('marginTop', headerH + 'px'); //ヘッダーの高さ分マージンを付ける
		}
});

// オーバーレイをクリックしたら
$('.overlay').click(function() {
		$(this).fadeOut(300); // オーバーレイ非表示
		$('header').removeClass('navOpen'); // class削除
		$('#wrap').removeClass('fixed'); // 固定解除
});

// スマホサイズからPCになったとき
$(window).on('load resize', function() {
		var breakpoint = 640;
		if (window.innerWidth > breakpoint) {
				$('header').removeClass('navOpen'); // class削除
				$('#wrap').removeClass('fixed'); // 固定解除
				$('.overlay').hide(); // オーバーレイ非表示
				$('header nav').css('marginTop', 0 + 'px'); // マージン削除
		}
});

まとめ

単なるナビゲーションでもナビゲーションのアイコンをちょっと工夫するだけで、サイトの印象が変わってきます。出来るだけシンプルにしたつもりなので、サイトに応じて適宜調整してみてください。

鹿
writer : 鹿
このブログを管理している鹿。Webデザインとガジェットが好き。
  • Feedly(RSS)で
    ブログを購読してみる
    購読する
  • Push7(プッシュ通知)で
    ブログを購読する
    購読する