CSSだけでハンバーガーメニュー【jqueryは使わない】


CSSだけでハンバーガーメニューを実装

ハンバーガーメニュー
ワタクシのおじいさんが教えてくれた初めてのjavascriptライブラリ、
それはjqueryでワタクシは4歳でした。
そのコードは面白く簡単で、
こんな素晴らしいjqueryを教えてもらえるワタクシはきっと特別な存在なのだと感じました。
今ではワタクシがおじいさん、孫に教えるのはもちろんjquery、
なぜなら、彼もまた特別な存在だからです。
はい、jqueryは言うまでもなく素晴らしいですね!
最近ではスマートフォン用サイトのド定番のハンバーガーメニュー、
これもjqueryで探せばたくさんありますが、
まぁ、CSSだけで出来るならそれに越したことはありませんね…
という事で、CSSだけで実装するハンバーガーメニューです。
デモ
一先ずデモをつくりました。
コード
htmlはこんな感じ
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
<!--▼▼ハンバーガーメニューここから▼▼--> <div class="hm_wrap"> <input id="hm_menu" type="checkbox" name="hm_menu" class="hm_menu_check"/> <label for="hm_menu" class="hm_btn"></label> <h2 class="hm_title">CSSだけでハンバーガーメニューを実装する方法</h2> <nav class="hm_menu_wrap"> <ul class="hm_list"> <li><a href="#">テキスト</a></li> <li><a href="#">テキスト</a></li> <li><a href="#">テキスト</a></li> <li><a href="#">テキスト</a></li> </ul> </nav> </div> <!--▲▲ハンバーガーメニューここまで▲▲--> |
CSSはこんな感じ
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 |
/* ▽▽ハンバーガーメニュー▽▽ ------------------------------------------------------- */ .hm_menu_check {/* チェックボックスを隠す */ display: none; } .hm_wrap { display: inline-block; position :fixed; top :0; left :0; width :100%; padding :10px; background :#fff; } .hm_title {/* ハンバーガーメニューオープン時の見出し */ position: relative; color: #999; display: inline-block; float: left; font-weight: 100; line-height: 30px; margin: 0 0 0 15px; opacity: 0; -webkit-transform: translate3d(0, -15px, 0); transform: translate3d(0, -15px, 0); -webkit-transition: -webkit-transform 0.6s, opacity 0.5s; transition: transform 0.6s, opacity 0.5s; z-index: 2; } /* ▽▽メニューボタン▽▽ */ .hm_btn { position: relative; width: 30px; height: 30px; cursor: pointer; display: block; float: left; z-index: 2; } .hm_btn::before { -webkit-box-shadow: #000 0 12px 0; box-shadow: #000 0 12px 0; } .hm_btn::after { bottom: 0; } .hm_btn::before, .hm_btn::after { width: 30px; height: 6px; background: #000; display: block; content: ''; position: absolute; -webkit-transition: -webkit-box-shadow 0.2s linear, -webkit-transform 0.2s 0.2s; transition: box-shadow 0.2s linear, transform 0.2s 0.2s; } /* △△メニューボタン△△ */ .hm_menu_wrap { width :100%; height :10000px; background: #fff; position: absolute; left: -100%; top: 0; -webkit-transition: left 0.4s; transition: left 0.4s; } /* ▽▽開閉時のアニメーション▽▽ */ .hm_menu_check:checked ~ .hm_title { opacity: 1; -webkit-transform: none; -ms-transform: none; transform: none; } .hm_menu_check:checked ~ .hm_btn::before { -webkit-box-shadow: transparent 0 0 0; box-shadow: transparent 0 0 0; -webkit-transform: rotate(45deg) translate3d(6px, 11px, 0); transform: rotate(45deg) translate3d(6px, 11px, 0); } .hm_menu_check:checked ~ .hm_btn::after { -webkit-transform: rotate(-45deg) translate3d(6px, -11px, 0); transform: rotate(-45deg) translate3d(6px, -11px, 0); } .hm_menu_check:checked ~ .hm_menu_wrap { left: 0; } /* △△開閉時のアニメーション△△ */ /* ▽▽メニュー内のリストスタイル▽▽ */ .hm_list { list-style-type: none; margin: 50px 0 0; padding: 0; } .hm_list li a { color: #777; display: block; overflow: hidden; padding: 8px 22px; position: relative; text-decoration: none; z-index: 1; } .hm_list li a::before {/* aタグマウスオーバー時の背景 */ background: #eee; content: ''; position: absolute; top: 0; right: 0; bottom: 100%; left: 0; -webkit-transition: bottom 0.4s; transition: bottom 0.4s; z-index: -1; } .hm_list li a:hover::before { bottom: 0; } .hm_list li a:hover::after { opacity: 0.5; -webkit-transform: translate3d(0, 0, 0); transform: translate3d(0, 0, 0); } /* メニュー内のリストスタイル△△ */ /* △△ハンバーガーメニュー△△ ------------------------------------------------------- */ |
以前に書いた
jqueryを使わないcssだけで実装するアコーディオンメニュー
と基本的には同じ事をしています。
見えないチェックボックスを用意して
チェックマークがある時にメニューが出現する、という要領。
おまけ
以前はハンバーガーメニューがまだまだ見慣れてない人も多く、
三本ラインの上か下に「MENU」or「メニュー」を入れるのが
ユーザビリティ的に良いと思ってましたが、
さすがにそろそろ大丈夫なんじゃなかろうかと思います。多分きっと…
なので今回のコードは三本ラインのみでデザインしています。
追記(2018.4.28)
メニュー外をクリックした際にメニューを閉じたいとの意見を頂いたので
デモのソースを多少弄りました。
htmlはこんな感じ
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
<!--▼▼ハンバーガーメニューここから▼▼--> <div class="hm_wrap"> <input id="hm_menu" type="checkbox" name="hm_menu" class="hm_menu_check"/> <label for="hm_menu" class="hm_btn"></label> <h2 class="hm_title">CSSだけでハンバーガーメニューを実装する方法</h2> <nav class="hm_menu_wrap"> <ul class="hm_list"> <li><a href="#">テキスト</a></li> <li><a href="#">テキスト</a></li> <li><a href="#">テキスト</a></li> <li><a href="#">テキスト</a></li> </ul> </nav> <div class="hm_menu_close"><label for="hm_menu"></label></div> </div> <!--▲▲ハンバーガーメニューここまで▲▲--> |
navの後に閉じる用のラベルを追加しています。
css追加部分
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
.hm_menu_close { width :0; height :0; background: #000; opacity :0; position: absolute; left: 70%; top: 0; -webkit-transition: all 0.3s; transition: all 0.3s; } .hm_menu_close label { display :block; width :100%; height :100%; cursor : pointer; } .hm_menu_check:checked ~ .hm_menu_close { width :30%; height :10000px; opacity :0.8; } |
css変更部分
1 2 3 4 5 6 7 8 9 10 |
.hm_menu_wrap { width :70%; height :10000px; background: #fff; position: absolute; left: -100%; top: 0; -webkit-transition: left 0.4s; transition: left 0.4s; } |
widthを70%に変更しました。
コニー
2017年10月18日 at 10:53 AM
初めまして。
シンプルですごく使いやすそうなので実装したいと思うのですが、スマホやタブレットではこのハンバーガーメニューを表示させて、PC(ブラウザ幅1024px以上)では横並びのグローバルメニューを表示させたいのですが、その場合どうしたら良いのでしょうか?
PCではチェックボックスがオフの時にナビゲーションを表示させるということは可能でしょうか?
お手数ですが教えていただけると助かります。
よろしくお願いいたします。
コニー
2017年10月18日 at 1:39 PM
午前中にお送りした質問ですが、自己解決できました!
お騒がせしてすいませんでした。
これからも参考にさせていただきますね。
有難うございました。
とっつぁん
2017年10月19日 at 3:24 AM
コメント頂きありがとうございます。
自己解決出来たとの事で、蛇足となってしまうと思いますが、
色々やり方はあるかと思いますが
CSSのメディアクエリで対応する事が多いと思います。
例:ハンバーガーメニューのCSSを以下のように記述する
@media screen and (max-width: 1080px) {
ハンバーガーメニューのCSS
}
みのりん
2018年3月30日 at 7:30 PM
初めまして。
理想の動きで、しかもCSSだけなのでぜひ使いたいと思っています。
デモでは左側にハンバーガーメニューが表示されるのですが、これを右側にしたい時って
どうしたら良いのでしょうか?
あまり詳しくないのでどうしたら良いのか分からずで….
教えていただければ嬉しいです!
よろしくお願いしますm(_ _)m
とっつぁん
2018年4月4日 at 12:26 AM
記事ではボタンは以下のようになっていますが
.hm_btn {
position: relative;
width: 30px;
height: 30px;
cursor: pointer;
display: block;
float: left;
z-index: 2;
}
右端に表示する場合は該当部分を以下のようにpositionを絶対値に変更して上下を調整する事になります。
.hm_btn {
position: absolute;
top: 10px;
right: 40px;
width: 30px;
height: 30px;
cursor: pointer;
display: block;
float: left;
z-index: 2;
}
参考になれば幸いです。
たかぷりん
2018年4月27日 at 11:23 AM
とても使いやすい魅力的なメニューですね!
イラストも凄く可愛いです^^
一つ質問なのですが、ハンバーガーボタン(×になった状態)を
クリックしなくとも
・メニュー選択後に自動でメニューが消える
もしくは
・メニュー外をクリックでメニューが消える
という挙動は可能なのでしょうか?
何卒ご教授よろしくお願いいたします。
とっつぁん
2018年4月28日 at 5:32 AM
ありがとうございます。
「メニュー選択後に消える」というのはページ内リンク等で利用する場合でしょうか?
(通常のリンクではクリックするとメニューは閉じると思うので…)
ラベルで出来れば良いのですが、aタグとの同時使用は出来ないようですので
記事の方向性とは離れますが
クリック時にjavascriptでチェックボックスを外すという方法が妥当かと思います。
メニュー外をクリックして閉じるというのはラベルを配置すれば何とかなりそうですね、
ワタクシも時間がある時にデモを弄ってみます。
参考になれば幸いです!
たかぷりん
2018年5月7日 at 9:35 AM
助言ありがとうございます!
説明不足ですみませんでした。ご指摘の通りページ内リンクのお話しでした。
>時間がある時にデモを弄ってみます。
ありがとうございます^^
ちょっと期待しております。
今回のご教授ありがとうございました!!
とっつぁん
2018年5月11日 at 5:05 AM
こっそりデモのメニュー内にのみ、
javascriptでページ内リンク時にチェックを外す指定を入れました。
head内のjavascriptを記述してaタグにonclickイベントを指定する事で
ページ内のチェックを外すよう指定しています。
スマートではない気がしますが
とりあえず目当ての挙動にしたい場合の参考になれば幸いです。
とむ
2018年5月6日 at 8:03 PM
色々なサイトで調べさせていただきましたが、
すごくわかりやすく、使いやすかったため実装させていただきました。
ありがとうございます。
1点質問なのですが、
ハンバーガーメニュー内のメニューが多く、見切れてしまいます。
メニュー内をスクロールすることは可能でしょうか?
ご教授いただけますと幸いです。
とっつぁん
2018年5月11日 at 4:16 AM
質問ありがとうございます。
なるほど、確かにたくさん詰め込みたくなりますよね…
記事のcssだと.hm_menu_wrapの高さをheight:10000pxと指定してあると思います。
これを書いた時期だとあまり使われていなかった高さの指定なのですが、
height :100vh;
overflow :auto;
にすることでスクロール可能になるかと思います。
それぞれ
100vhは「ビューポートの高さ100%分」という指定、
overflowは見切れてしまう部分の対処方法の指定です。
参考になれば幸いです。
とむ
2018年5月11日 at 3:56 PM
解決できました!
ご回答ありがとうございました!
こじこじ
2018年5月28日 at 4:31 PM
はじめまして。
ずーーーーっと探していたハンバーガーメニューの作り方をとても分かりやすく解説してくださり、
感動しています。本当にありがとうございます!(涙)
cssがあまり詳しくなくて勉強不足で申し訳ないのですが、
教えて頂いた通り、キホンはうまくいきました。
が、致命的にどうしてもうまくいかない点があり挫折寸前で、
もしお分かりでしたらご教示いただきたく、失礼します。
現在Smart sliderとInstagramfeedというプラグインを使っています。
で、その画像が表示されている部分でメニューをオープンすると、
SliderやInstagramの画像が最上層で表示されてしまい、重なるメニューが見えなくなってしまうのです。
z-indexの数字をいじってみたりしたのですが、まったく変わらず。
メニューを最上層に表示する方法がお分かりでしたら、教えていただけますと幸いです。
とっつぁん
2018年6月1日 at 6:10 AM
うーん…
詳しく見てみないと何とも言えませんが、
.hm_wrap {
display: inline-block;
position :fixed;
top :0;
left :0;
width :100%;
padding :10px;
background :#fff;
}
の部分にz-index :10000;(インスタ等の画像より高数値)を指定しても変わらないでしょうか?
変わらないようでしたら
まずはブラウザのキャッシュを疑ってスーパーリロードしてみてください。
一応念のためですが、
z-indexはpositionを同時に指定しないと仕事をしません。
とりあえず今思い付いたのはそんなところです。
参考になれば幸いです。
じょー
2018年10月8日 at 11:18 AM
初めまして!導入させていただきまして、大満足です♡
ちなみにハンバーガーとバツボタンのサイズを小さくするにはどうすればいいでしょうか…
何箇所か触ってみたのですが、ハンバーガーの線の間隔がズレたり、バツも変な形に…ww
ご教授いただけると幸いです!!
とっつぁん
2018年10月9日 at 7:24 AM
メニューのボタンのCSSは以下の部分で
beforeが上、afterが下の棒です!(真ん中はbeforeの影)
/* ▽▽メニューボタン▽▽ */
.hm_btn {
position: relative;
width: 30px;
height: 30px;
cursor: pointer;
display: block;
float: left;
z-index: 2;
}
.hm_btn::before {
-webkit-box-shadow: #000 0 12px 0;
box-shadow: #000 0 12px 0;
}
.hm_btn::after {
bottom: 0;
}
.hm_btn::before,
.hm_btn::after {
width: 30px;
height: 6px;
background: #000;
display: block;
content: ”;
position: absolute;
-webkit-transition: -webkit-box-shadow 0.2s linear, -webkit-transform 0.2s 0.2s;
transition: box-shadow 0.2s linear, transform 0.2s 0.2s;
}
/* △△メニューボタン△△ */
なのでこの部分の
widthとheightを編集すれば大きさが変わると思います
◆.hm_btn::before,.hm_btn::afterのheight:6px;は棒の高さ
◆.hm_btnのheight:30px;は棒と隙間合計の高さ
◆.hm_btn::beforeのbox-shadowが真ん中の棒で、この場合上の棒から12px離れた位置にあります
若干面倒なのですがその辺り適当に調整してください。
以下は編集しなくても大丈夫かもですが…
バツ印になる部分は以下の部分です
/* ▽▽開閉時のアニメーション▽▽ */
.hm_menu_check:checked ~ .hm_title {
opacity: 1;
-webkit-transform: none;
-ms-transform: none;
transform: none;
}
.hm_menu_check:checked ~ .hm_btn::before {
-webkit-box-shadow: transparent 0 0 0;
box-shadow: transparent 0 0 0;
-webkit-transform: rotate(45deg) translate3d(6px, 11px, 0);
transform: rotate(45deg) translate3d(6px, 11px, 0);
}
.hm_menu_check:checked ~ .hm_btn::after {
-webkit-transform: rotate(-45deg) translate3d(6px, -11px, 0);
transform: rotate(-45deg) translate3d(6px, -11px, 0);
}
.hm_menu_check:checked ~ .hm_menu_wrap {
left: 0;
}
/* △△開閉時のアニメーション△△ */
必要であればそれぞれ
-webkit-transform: rotate(45deg) translate3d(6px, 11px, 0);
transform: rotate(45deg) translate3d(6px, 11px, 0);
の値の部分を変更してください。
ののの
2018年11月29日 at 7:12 PM
メニュー外クリックで閉じるの挙動がうまくいきません。
そもそも黒い背景がバツボタンの高さにしか出てこず、paddingで無理やり広げることはできるのですが押せません。
どのような原因が考えられますでしょうか?
とっつぁん
2018年11月30日 at 1:20 PM
うーん、症状を再現できるかちょっと試してみたのですが
実際に見てみないとよくわからないですね。
メニュー外クリックで閉じる該当部分の役割については
.hm_menu_closeに色の指定があり、
内包するlabelをクリックorタップすることで
チェックマークが外れるようになっていますので。
黒い背景が下まで広がっていても中のlabelがクリックできなければ動作しません。
ただ、記事のcssでも100%広がるよう記述しているのでまったく別の問題かもしれませんね…
タイプミス・コピペミスという場合も考えられますので
一度、できるだけコンテンツがない状態のページに実装して挙動を確認したほうが良いかもしれないですね。
はぐたん
2019年4月17日 at 11:19 PM
はじめまして!
レスポンシブでハンバーガーメニューを実装したいと思い、
色々と探し回りましたが、やっと理想的なメニューに出会えました。
ありがとうございます。
CSSだけでこんなにオシャレに出来るのは感動ものでした。
ただ、swiperのスライダーやYouTubeのiframe埋め込みなどがある部分は、
メニューを開いても、iframeの後ろに隠れてしまいます。
何か対策はありますか?
よろしくお願いします。
とっつぁん
2019年5月2日 at 7:31 PM
はぐたんさんはじめまして、
Youtubeのiframe等の方が開いたメニューより上に来るという事は
おそらく該当箇所のz-indexの指定がメニューより大きいのだと思います。
試しにデモページにyoutubeで適当な動画を埋め込んでみました。