Top

checkboxを使ってCSSだけでハンバーガーメニュー

CSS だけでハンバーガーメニューを設置する という記事を以前書いたのですが、iPhone など CSS のセレクタで hover が効かないデバイスではメニューが開きませんでした。今回の記事はそれを解消すべく input 要素の checkbox を使う事で、hover ではなく click に反応するようにして iPhone でも CSS だけでメニューが開くようにしてみます。

当然、iPhone 以外の PC ブラウザ、アンドロイドでも問題なく開閉します。

check-and-hamburger

checkbox って?

checkbox とは input 要素で選ぶことが出来る種類の1つで、下のデモのようにクリックすることで 〆 マークがついたり消えたりする要素です。アンケートやフォームなどでよく使われれています。

input 要素に共通して言えることですが、label 要素というのを個々に設定することが出来ます。label とはその input 要素の名前などを入れることが出来る要素で、例えば checkbox に label 要素を「チェックボックス」として付けた場合、チェックボックス本体だけでなく、label 要素、つまり「チェックボックス」の文字列をクリクしてもボックス本体のマークがついたり消えたりします。

デモ

デモの HTML

<input id="demo" type="checkbox" value="off"><label for="demo">チェックボックス</label>

input 要素の id と label 要素の for の値をそろえることで一体化させることが出来ます。 label 要素の「チェックボックス」の文字列をクリックしてもマークがつくことが確認できますね。

この特性を使ってハンバーガーメニューを作ってみます。実際にこのページでも右上にハンバーガーメニューを設置してみました。

hamburgermenu

スポンサーリンク

ハンバーガーメニューの作り方

HTML

<input id="menu-cb" type="checkbox" value="off">
<label id="menu-icon" for="menu-cb">≡</label>
<label id="menu-background" for="menu-cb"></label>
<div id="ham-menu">
    <ul>
        <li>メニュー1</li>
        <li>メニュー2</li>
        <li>メニュー3</li>
    </ul>
</div>

CSS

#ham-menu {
    background-color: #fff; /*メニュー背景色*/
    box-sizing: border-box;
    height: 100%;
    padding: 10px 40px; /*メニュー内左右上下余白*/
    position: fixed;
    right: -300px; /*メニュー横幅 width と合わせる*/
    top: 0;
    transition: transform 0.3s linear 0s; /*0.3s はアニメーションにかかる時間*/
    width: 300px; /*メニュー横幅*/
    z-index: 1000;
}

#menu-background {
    background-color: #333; /*黒背景*/
    display: block;
    height: 100%;
    opacity: 0;
    position: fixed;
    right: 0;
    top: 0;
    transition: all 0.3s linear 0s; /*0.3s はアニメーションにかかる時間*/
    width: 100%;
    z-index: -1;
}

#menu-icon {
    background-color: #fff; /*アイコン部分背景色*/
    border-radius: 0 0 0 10px; /*左下角丸*/
    color: #333; /*アイコン(フォント)色*/
    cursor: pointer;
    display: block;
    font-size: 50px; /*アイコン(フォント)サイズ*/
    height: 50px; /*アイコン縦高さ*/
    line-height: 50px; /*縦位置中央化*/
    position: fixed;
    right: 0;
    text-align: center;
    top: 0;
    width: 50px; /*アイコン横幅*/
    transition: all 0.3s linear 0s; /*0.3s はアニメーションにかかる時間*/
    z-index: 1000;
}

#menu-cb {
    display: none; /*チェックボックス本体は消しておく*/
}

#menu-cb:checked ~ #ham-menu,
#menu-cb:checked ~ #menu-icon {
    transform: translate(-300px); /*メニュー本体横幅 width と合わせる*/
}

#menu-cb:checked ~ #menu-background {
    opacity: 0.5;
    z-index: 999;
}

HTML のポイントは label を2つ配置し、片方を「≡」のアイコン用、もう片方を黒背景用にします。2つ label 要素を使っていいのか定かではありませんが、for の値を設定することでどちらも label として機能します。

CSS の疑似セレクタに :checked というものがあり、チェックボックスがチェックされてる状態を指定できるものがあります。label 要素である ≡ アイコンをクリックするとチェックボックスがチェックされてメニューが開く仕組みです。

黒背景自体も label 要素にすることで ≡ アイコンだけでなく、黒背景をクリックしてもメニューが閉じるようになっています。これは label 要素である黒背景がチェックボックス本体と同じ機能をもっているためです。そして、チェックボックス本体は display:none で消しておきます。CSS で消しても label をクリックすることでチェックの有無が切り替わります。

まとめ

前回の記事で iPhone だけメニューが開閉しないので悲しい感じでしたが、これで iPhone でも CSS だけでハンバーガーメニューを設置出来ました。

checkbox でハンバーガーメニューを作ることの弱点は :checked が IE9 以上の対応なので古い IE には使えない事ぐらいです。特に問題はなさそうです。

before などの疑似要素を使ってクリックされると ≡ のアイコンを変化させたりなんかも出来そうです。

  • メニュー1
  • メニュー2
  • メニュー3
  1. いまのひと

    わかりやすい記事をありがとうございます。
    このサイトの通りメニューを作ってみたのですが、サイト上どこをクリックしてもメニューが開いてしまうようになりました。
    なにか解決方法はありますでしょうか。よろしくお願いします。

    2017-01-04 0:37Reply
    • bodyなどの要素の高さが存在しない状況だと黒背景要素が常に表に出てきている状況になってしまうため、そのような現象が起こります。

      通常の実装であれば起こらない状況だと思うので、body:1000pxなど仮の値を設定して状況が改善すればその辺りから治してみてください。

      2017-01-04 8:48Reply
  2. 只今勉強中

    使わせて頂いています。
    1点教えて下さい。
    メニューが増えた場合、画面より下側に、はみ出したメニューが表示されません。
    背景がスクロールしてしまい、手前のメニューはスクロールしません。
    何か良い方法はありますでしょうか?

    2017-02-23 8:15Reply
    • CSSだけでと考えるとすれば、スクロールできるようにするには ul 要素自体にoverflow-y: scrollなどを適用させてスクロールさせるしか無いです。

      2017-02-23 22:52Reply
  3. shinya666

    利用させていただいているのですが、iPhone6でメニューをタップしても、展開することはするのですが、リストが表示されず、グレーの背景(#333)だけが広がるのですが、原因は何が考えられますか?

    2017-04-18 15:09Reply
    • 考えられる原因は無限にありますが、お使いのiPhone6のアップデートをしばらく行っていないからではないでしょうか。
      古い仕様のiPhoneは基本的にフォローしていないのでならないということが考えられます。

      iPhone6をアップデートするか、もしそれが嫌なら「transform ベンダープレフィクス」あたりで検索してもらえれば対処法が出てくると思います。

      2017-04-19 7:26Reply