jQueryとCSS3でマテリアルデザインのハンバーガーメニューを実装してみる
このブログのリニューアルしたときにマテリアルデザインのハンバーガーメニューをjQueryとCSS3を使って再現してみました。Googleのアプリで初めて見た時には面白くて無駄に何度もアニメーションさせていましたw
今回は自分の備忘録としてまとめておきます。
※本ページは広告・アフィリエイトプログラムにより収益を得ています。
ハンバーガーメニューとは
当ブログで採用している三本線のメニューのことです。
マテリアルデザインだとメニューを展開した時にアニメーションしながら矢印に変わっていきます。
どれも見ていて気持ちがいいアニメーションですね。
デモ・動作について
これらを踏まえてまずはデモをご覧ください。
左上にある三本の線を押すと…
アニメーションしながら矢印へと変化していきます。そして、左からメニューがスライドして表示されます。
対応ブラウザ・ソース解説
Firefox最新版・Chrome最新版で確認しております。
IE9ではCSS3 animationやtransitionの対応していないため、ハンバーガーメニューとメニュー開閉のアニメーションが動作しません。
IE8以下ではハンバーガーメニューが一本線になってしまいました。IE8以下は画像で対応することになりそうですね。
HTML
<!DOCTYPE html>
<!--[if lt IE 7 ]> <html lang="ja" id="ie6" class="ie"> <![endif]-->
<!--[if IE 7 ]> <html lang="ja" id="ie7" class="ie"> <![endif]-->
<!--[if IE 8 ]> <html lang="ja" id="ie8" class="ie"> <![endif]-->
<!--[if IE 9 ]> <html lang="ja" id="ie9" class="ie"> <![endif]-->
<!--[if (gt IE 9)|!(IE)]><!--> <html> <!--<![endif]-->
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Material Design Hamburger Menu</title>
<link rel="stylesheet" href="css/reset.css">
<link rel="stylesheet" href="css/style.css">
<link rel="stylesheet" type="text/css" href='http://fonts.googleapis.com/css?family=Roboto:500,300,700,400'>
<!--[if lt IE 9]><script type="text/javascript" src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script><![endif]-->
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<script src="js/script.js"></script>
</head>
<body>
<div id="wrap">
<header>
<h1>Material Design<br>
Hamburger Menu</h1>
<div class="navBtn">
<button class="navIcon"><span class="iconLayer"></span></button>
<!-- /.navBtn --></div>
<div class="menu menuOff">
<ul>
<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>
<li><a href="#">メニュー</a></li>
</ul>
<!-- / .menu menuOff --></div>
</header>
<div id="contents">
<p class="img"><img src="img/deer.jpg" width="960" height="640" alt="かわいい鹿"></p>
<h2>シカ</h2>
<p>シカ(鹿)は、鯨偶蹄目シカ科 (Cervidae) に属する哺乳類の総称である。ニホンジカ、トナカイ、ヘラジカなどが属しており、約16属36種が世界中の森林に生息している。</p>
<p>日本国内で単にシカと言うときは、ニホンジカ Cervus nippon を指すことが多い。1980年頃に房総半島で野生化した外来種のキョンを除き、ニホンジカは日本に分布する唯一のシカ科動物であり、大きな哺乳類の少ない日本ではニホンカモシカと並ぶ代表的な大型動物である。<br>
なお、ニホンジカは、他国に分布する亜種も含め、英語では一般的に「sika deer」(「sika」は日本語の「シカ」に由来)と呼ばれる。</p>
<p>牛・豚・馬などの皮革に比べて鹿皮は薄く柔らかいため、なめして細かい加工を要する手袋などに適し、時に柔らかい靴やソファーなどの材料となる。また、枝角はナイフの柄やボタンなどに用いられている。鹿の枝角は、アントラ(Antler)と呼ばれている。鹿の角(鹿茸)は乾燥粉末や黒焼末は様々な効能を持つとして民間療法で用いられる。日本では鹿肉のことを「もみじ」と呼び、様々な肉料理に調理される。味は一般に柔らかい牛肉に近い。ちなみに馬肉は「さくら」、イノシシ肉は「ぼたん」と呼ぶが、鹿肉は「鹿」が秋の季語であることから紅葉を連想したものであり、馬肉とイノシシ肉は色から連想された呼称である(花札でも「鹿にもみじ」の絵札がある)。
シカの蹄には、ヤマビルが穴をあけて寄生すること(有穴腫瘤)が知られており、ヤマビルの生息域の拡大にシカが関与していることが疑われている[2]。</p>
<p>Wikipediaより引用。鹿の写真は<a href="http://www.imgstyle.info/detail.php?id=724">奈良 鹿・側面8 4200pxの無料・フリー写真素材</a>から。</p>
<!-- / #contents --></div>
<footer>
<p>© 2015 Creator Clip</p>
</footer>
<!-- / #wrap --></div>
</body>
</html>
CSS
@charset "utf-8";
#wrap {
font-family: 'Roboto', "ヒラギノ角ゴ Pro W3", "Hiragino Kaku Gothic Pro", "メイリオ", Meiryo, Osaka, "MS Pゴシック", "MS PGothic", sans-serif;
}
/**********************************
ヘッダー
**********************************/
header {
/* メニューを開いた時に
オーバーレイの上に来るように絶対指定 */
position:absolute;
top:0;
left:0;
width:100%;
color:#fff;
text-align:center;
text-shadow:1px 1px 0 rgba(0,0,0,0.2);
background:#03A9F4;
z-index:9999; /* 最前面に来るように */
}
header h1 {
padding:0.5em;
font-size:2.5em;
}
header h1 br {
display:none;
}
/**********************************
メニュー
**********************************/
.menu {
overflow-y:auto; /* 縦方向のみスクロール */
position: absolute;
top:0;
left:0;
width: 30%;
max-width:320px; /* 横に広がり過ぎないように */
color: #333;
font-size:110%;
background: #eee;
text-align:left;
z-index:9999;
/* アニメーション */
-webkit-transition:0.2s ease-in-out;
-moz-transition:0.2s ease-in-out;
transition:0.2s ease-in-out;
}
.menu ul li a {
display:block;
padding:1.25em;
color:#555;
font-weight:300;
text-shadow:none;
text-decoration:none;
}
.menu ul li a:hover {
color:#fff;
background:#81D4FA;
}
/* メニューON/OFF */
.menuOff {
-webkit-transform:translate3d(-100%, 0, 0);
-moz-transform:translate3d(-100%, 0, 0);
transform:translate3d(-100%, 0, 0);
z-index:9999; /* 最前面に来るように */
}
.menuOn {
box-shadow: 8px 8px 20px 0 rgba(0, 0, 0, 0.2);
-webkit-transform:translate3d(0, 0, 0);
-moz-transform:translate3d(0, 0, 0);
transform:translate3d(0, 0, 0);
}
.ie .menuOff {
left:-100%; /* IE向け */
}
.ie .menuOn {
left: 0; /* IE向け */
}
/* ナビゲーション以外固定 */
.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;
}
/**********************************
ナビゲーションアイコン
**********************************/
.navBtn {
position:absolute;
top:0.2em;
left:1em;
}
/* IE8以下はアイコン位置調整 */
#ie8 .navBtn,
#ie7 .navBtn,
#ie6 .navBtn {
top:30px;
}
.navBtn button {
display: block;
border: none;
background: none;
outline: 0;
-webkit-tap-highlight-color:rgba(0,0,0,0);
−moz−tap-highlight-color:rgba(0,0,0,0);
tap-highlight-color:rgba(0,0,0,0);
}
.navIcon {
padding: 2rem 1rem;
cursor: pointer;
-webkit-transform: scale(0.8);
-moz-transform: scale(0.8);
transform: scale(0.8);
}
/* アイコンレイヤー */
.iconLayer {
position: relative;
display: block;
width: 50px;
height: 7px;
background:#0277BD;
-webkit-animation-duration: 300ms;
-moz-animation-duration: 300ms;
animation-duration: 300ms;
-webkit-animation-timing-function: ease-in-out;
-moz-animation-timing-function: ease-in-out;
animation-timing-function: ease-in-out;
}
.iconLayer:before, .iconLayer:after {
content: '';
position: absolute;
left: 0;
display: block;
width: inherit;
height: 7px;
background: inherit;
-webkit-animation-duration: 300ms;
-moz-animation-duration: 300ms;
animation-duration: 300ms;
-webkit-animation-timing-function: ease-in-out;
-moz-animation-timing-function: ease-in-out;
animation-timing-function: ease-in-out;
}
.iconLayer:before {
bottom: 200%;
}
.iconLayer:after {
top: 200%;
}
/**********************************
ナビアイコン:矢印
**********************************/
.arrow {
-webkit-animation-name: navIconSlide;
-moz-animation-name: navIconSlide;
animation-name: navIconSlide;
-webkit-animation-fill-mode: forwards;
-moz-animation-fill-mode: forwards;
animation-fill-mode: forwards;
}
@-webkit-keyframes navIconSlide {
0% {
}
100% {
-webkit-transform: rotate(180deg);
transform: rotate(180deg);
}
}
@-moz-keyframes navIconSlide {
0% {
}
100% {
-moz-transform: rotate(180deg);
transform: rotate(180deg);
}
}
@keyframes navIconSlide {
0% {
}
100% {
transform: rotate(180deg);
}
}
/* ナビアイコン:矢印:before */
.arrow:before {
-webkit-animation-name: navIconSlideBefore;
-moz-animation-name: navIconSlideBefore;
animation-name: navIconSlideBefore;
-webkit-animation-fill-mode: forwards;
-moz-animation-fill-mode: forwards;
animation-fill-mode: forwards;
}
@-webkit-keyframes navIconSlideBefore {
0% {
}
100% {
margin: 0% 31%;
width: 75%;
-webkit-transform: rotate(45deg);
transform: rotate(45deg);
}
}
@-moz-keyframes navIconSlideBefore {
0% {
}
100% {
margin: 0% 31%;
width: 75%;
-moz-transform: rotate(45deg);
transform: rotate(45deg);
}
}
@keyframes navIconSlideBefore {
0% {
}
100% {
margin: 0% 31%;
width: 75%;
transform: rotate(45deg);
}
}
/* ナビアイコン:矢印:after */
.arrow:after {
-webkit-animation-name: navIconSlideAfter;
-moz-animation-name: navIconSlideAfter;
animation-name: navIconSlideAfter;
-webkit-animation-fill-mode: forwards;
-moz-animation-fill-mode: forwards;
animation-fill-mode: forwards;
}
@-webkit-keyframes navIconSlideAfter {
0% {
}
100% {
margin: 0% 31%;
width: 75%;
-webkit-transform: rotate(-45deg);
transform: rotate(-45deg);
}
}
@-moz-keyframes navIconSlideAfter {
0% {
}
100% {
margin: 0% 31%;
width: 75%;
-moz-transform: rotate(-45deg);
transform: rotate(-45deg);
}
}
@keyframes navIconSlideAfter {
0% {
}
100% {
margin: 0% 31%;
width: 75%;
transform: rotate(-45deg);
}
}
/**********************************
ナビアイコン:ハンバーガー
**********************************/
.hamburger {
-webkit-animation-name: navIconSlideFrom;
-moz-animation-name: navIconSlideFrom;
animation-name: navIconSlideFrom;
}
@-webkit-keyframes navIconSlideFrom {
0% {
-webkit-transform: rotate(-180deg);
transform: rotate(-180deg);
}
100% {
}
}
@-moz-keyframes navIconSlideFrom {
0% {
-moz-transform: rotate(-180deg);
transform: rotate(-180deg);
}
100% {
}
}
@keyframes navIconSlideFrom {
0% {
transform: rotate(-180deg);
}
100% {
}
}
/* ナビアイコン:ハンバーガー:before */
.hamburger:before {
-webkit-animation-name: navIconSlideBeforeFrom;
-moz-animation-name: navIconSlideBeforeFrom;
animation-name: navIconSlideBeforeFrom;
}
@-webkit-keyframes navIconSlideBeforeFrom {
0% {
margin: 3% 37%;
width: 50%;
-webkit-transform: rotate(45deg);
transform: rotate(45deg);
}
100% {
}
}
@-moz-keyframes navIconSlideBeforeFrom {
0% {
margin: 3% 37%;
width: 50%;
-moz-transform: rotate(45deg);
transform: rotate(45deg);
}
100% {
}
}
@keyframes navIconSlideBeforeFrom {
0% {
margin: 3% 37%;
width: 75%;
transform: rotate(45deg);
}
100% {
}
}
/* ナビアイコン:ハンバーガー:after */
.hamburger:after {
-webkit-animation-name: navIconSlideAfterFrom;
-moz-animation-name: navIconSlideAfterFrom;
animation-name: navIconSlideAfterFrom;
}
@-webkit-keyframes navIconSlideAfterFrom {
0% {
margin: 3% 37%;
width: 75%;
-webkit-transform: rotate(-45deg);
transform: rotate(-45deg);
}
100% {
}
}
@-moz-keyframes navIconSlideAfterFrom {
0% {
margin: 3% 37%;
width: 75%;
-moz-transform: rotate(-45deg);
transform: rotate(-45deg);
}
100% {
}
}
@keyframes navIconSlideAfterFrom {
0% {
margin: 3% 37%;
width: 75%;
transform: rotate(-45deg);
}
100% {
}
}
/**********************************
コンテンツ
**********************************/
#contents {
width:92%;
max-width:960px;
position:relative;
margin:30px auto;
}
#contents h2 {
margin:1em 0;
color:#634a32;
font-size:2em;
}
#contents p {
margin:1em 0;
color:#634a32;
line-height:1.7;
}
/**********************************
フッター
**********************************/
footer {
padding:1em 0;
color:#fff;
background:#555;
}
footer p {
width:92%;
max-width:960px;
margin:0 auto;
}
/**********************************
レスポンシブ
**********************************/
@media screen and (max-width: 800px) {
header h1 {
line-height:1.3;
}
header h1 br {
display:block;
}
header .menu {
width:50%;
}
}
@media screen and (max-width: 480px) {
header h1 {
font-size:1.2em;
}
header .navBtn {
top:0;
left:0;
-webkit-transform: scale(0.5);
-moz-transform: scale(0.5);
transform: scale(0.5);
}
header .menu {
width:70%;
}
}
jQuery
$(function(){
// ===============================
// ハンバーガーアイコン動作関係
// ===============================
// ナビアイコンをクリックしたら
$('.navIcon').click(function(){
$('.overlay').toggle(); // オーバーレイ表示切替
$('.menu').toggleClass('menuOn'); // サイドメニュー表示切替
$('#wrap').toggleClass('fixed'); // コンテンツ固定
if ($('.iconLayer').hasClass('arrow')) { // アイコンが矢印なら
$('.iconLayer').removeClass('arrow').addClass('hamburger'); // ハンバーガーメニューに
} else { // それ以外なら
$('.iconLayer').removeClass('hamburger').addClass("arrow"); // 矢印
}
return false;
});
// オーバーレイ作成
$('#contents').prepend('<div class="overlay"></div>');
// オーバーレイをクリックしたら
$('.overlay').click(function(){
$(this).fadeOut(300); // オーバーレイ非表示
$('.menu').removeClass('menuOn'); // メニュー非表示
$('#wrap').removeClass('fixed'); // 固定解除
$('.iconLayer').removeClass('arrow').addClass('hamburger'); // ハンバーガーメニューに
});
// ===============================
// メニュー動作関係
// ===============================
// サイドナビゲーション高さ指定
function winHeight() {
var winH = $(window).height();
var headerH = $('header').height();
var winH = winH - headerH; // ヘッダーの高さを引く
$('.menu').css({
'height': winH + 'px',
'top': headerH + 'px'
});
$('#contents').css('marginTop', headerH + 30 + 'px');
}
winHeight();
// リサイズしたら再度実行
$(window).resize(function(){
winHeight();
});
// サイドメニュー説明文
$('.menuHeader figcaption').click(function(){
$('.menu .txt').slideToggle();
});
});
WordPressで使用する場合
WordPressでjQueryを使用する際には「$」記号を「jQuery」に置き換えると動作するようになります。
ここの解説が分かりやすかったです。
- WordPressでjQueryを使うときに、問題なく動作させる為の基礎知識やTipsと、動かない場合の対処例 – かちびと.net
- WordPressでjQueryが動かないという人へ – WordPressにイメージスライダーを付けてみよう
jQuery(function(){
// ===============================
// ハンバーガーアイコン動作関係
// ===============================
// ナビアイコンをクリックしたら
jQuery('.navIcon').click(function(){
jQuery('.overlay').toggle(); // オーバーレイ表示切替
jQuery('.menu').toggleClass('menuOn'); // サイドメニュー表示切替
jQuery('#wrap').toggleClass('fixed'); // コンテンツ固定
if (jQuery('.iconLayer').hasClass('arrow')) { // アイコンが矢印なら
jQuery('.iconLayer').removeClass('arrow').addClass('hamburger'); // ハンバーガーメニューに
} else { // それ以外なら
jQuery('.iconLayer').removeClass('hamburger').addClass("arrow"); // 矢印
}
return false;
});
// オーバーレイ作成
jQuery('#contents').prepend('<div class="overlay"></div>');
// オーバーレイをクリックしたら
jQuery('.overlay').click(function(){
jQuery(this).fadeOut(300); // オーバーレイ非表示
jQuery('.menu').removeClass('menuOn'); // メニュー非表示
jQuery('#wrap').removeClass('fixed'); // 固定解除
jQuery('.iconLayer').removeClass('arrow').addClass('hamburger'); // ハンバーガーメニューに
});
// ===============================
// メニュー動作関係
// ===============================
// サイドナビゲーション高さ指定
function winHeight() {
var winH = jQuery(window).height();
var headerH = jQuery('header').height();
var winH = winH - headerH; // ヘッダーの高さを引く
jQuery('.menu').css({
'height': winH + 'px',
'top': headerH + 'px'
});
jQuery('#contents').css('marginTop', headerH + 30 + 'px');
}
winHeight();
// リサイズしたら再度実行
jQuery(window).resize(function(){
winHeight();
});
// サイドメニュー説明文
jQuery('.menuHeader figcaption').click(function(){
jQuery('.menu .txt').slideToggle();
});
});
参考リンク
ハンバーガーメニューは以下のサイトを元に作成しております。ハンバーガーメニュー以外のオーバーレイやメニュー以外の固定表示などを今回新たに実装しました。
- Material Design Hamburger
- Search Results for material design on CodePen
- Delightful details – Animation – Google design guidelines
アイコンを矢印ではなく×ボタンにしたい場合は、以下の記事が参考になります。
まとめ
今後流行り始めそうなマテリアルデザインをいち早く取り入れた当ブログですが、粗が目立つので定期的に修正を行っております。不具合などがあれば引き続き受け付けておりますので、ご連絡いただけると助かります!