ハンバーガーメニューをCSSだけで作る方法

今回伝えたいこと

レスポンシブデザインにおいて、ブラウザの幅がスマートフォンサイズになった際に、ナビゲーションを効率的に格納するハンバーガーメニューの導入は一般的です。
今回は、JavaScriptを一切使用せず、CSSとHTMLのみでこのハンバーガーメニューを実装する方法をご紹介します。

テーマを決めた背景

Web制作の学習を進める中で、デザインカンプから実際にレスポンシブなWebサイトを制作する課題に取り組みました。この際、スマートフォン表示でのハンバーガーメニューの実装が必要になりました。
一般的にハンバーガーメニューはJavaScript(JS)を用いて開閉を制御しますが、調査を進める中で、CSSの機能だけでもこれを実現できることを知りました。
今回は、その時に学んだ「JSを使用しない、CSSのみで実装するハンバーガーメニュー」の方法を皆さんと共有したいと思います。この手法は、シンプルな仕組みでメニュー開閉を実現でき、JSの知識がない方でもレスポンシブデザインの基礎を学ぶ上で非常に役立つと思います。

技術内容

See the Pen Untitled by daisuke (@daisuke-the-sans) on CodePen.

①ボタンの実装

まずは3本線のよく見るハンバーガーボタンを実装します。

HTML


        <div class="hamburger-menu">
            <input type="checkbox" id="menu-btn-check">
            <label for="menu-btn-check" class="menu-btn"><span></span></label>
            

CSS


        .menu-btn {
        position: fixed;
        top: 10px;
        right: 10px;
        display: flex;
        height: 60px;
        width: 60px;
        justify-content: center;
        align-items: center;
        z-index: 90;
        background-color: #3584bb;
        }
        
        .menu-btn span,
        .menu-btn span:before,
        .menu-btn span:after {
        content: '';
        display: block;
        height: 3px;
        width: 25px;
        border-radius: 3px;
        background-color: #ffffff;
        position: absolute;
        }
        
        .menu-btn span:before {
        bottom: 8px;
        }
        
        .menu-btn span:after {
        top: 8px;
        }

        #menu-btn-check:checked~.menu-btn span {
        background-color: rgba(255, 255, 255, 0);
        /*メニューオープン時は真ん中の線を透明にする*/
        }
        
        #menu-btn-check:checked~.menu-btn span::before {
        bottom: 0;
        transform: rotate(45deg);
        }
        
        #menu-btn-check:checked~.menu-btn span::after {
        top: 0;
        transform: rotate(-45deg);
        }
        
        #menu-btn-check {
        display: none;
        }
        
  • ボタンが押されたかの判断は、checkboxで判断します。
  • position:fixed;でスクロールしてもついてくるように固定します。
  • アイコンはspanタグを疑似要素(before,after)と絶対配置(position:absolute;)を用いて上下に分けて3本線を作ります。
  • 間接セレクタ(~)で、ある要素がチェックされたらその後ろにある別の要素の見た目を変更するという操作を行います。具体的には真ん中の線を消して上下の線をバツ印に変形させます。
  • 画面上に出てくるcheckboxを見えないように消します。

②メニュー部分の実装

先ほどのHTMLに追加してメニュー部分を実装していきます。

HTML


                <div class="hamburger-menu">
                    <input type="checkbox" id="menu-btn-check">
                    <label for="menu-btn-check" class="menu-btn"><span></span></label>
                    <!--ここからメニュー-->
                    <div class="menu-content">
                        <ul>
                            <li>
                                <a href="#">メニューリンク1</a>
                            </li>
                            <li>
                                <a href="#">メニューリンク2</a>
                            </li>
                            <li>
                                <a href="#">メニューリンク3</a>
                            </li>
                        </ul>
                    </div>
                    <!--ここまでメニュー-->
                </div>
                

CSS


        .menu-content {
        width: 100%;
        height: 100%;
        position: fixed;
        top: 0;
        left: 100%;/*leftの値を変更してメニューを画面外へ*/
        z-index: 80;
        background-color: #3584bb;
        transition: all 0.5s;/*アニメーション設定*/
        }
        .menu-content ul {
        padding: 70px 10px 0;
        }
        
        .menu-content ul li {
        border-bottom: solid 1px #ffffff;
        list-style: none;
        }
        
        .menu-content ul li a {
        display: block;
        width: 100%;
        font-size: 15px;
        box-sizing: border-box;
        color: #ffffff;
        text-decoration: none;
        padding: 9px 15px 10px 0;
        position: relative;
        }
        
        #menu-btn-check:checked~.menu-content {
        left: 0;
        /*メニューを画面内へ*/
        }
        
  • position:fixed;でスクロールしてもついてくるように固定します。
  • z-indexをボタンよりも小さくして背面にもってきます。
  • 本来は左上にいるがハンバーガーボタンを押していないときは隠しておきたいため、left 100%で右の画面外に隠します。
  • ボタンを押したときに、右からスライドして出てきてほしいため間接セレクタと、transitionを入れている。

課題点

CSSのみでボタンをつくる上での課題点は、checkboxにフォーカスするという構造上、"開く閉じる"の制御が柔軟にできない。また、アニメーションをCSSだけで付与する際にcheckedの切り替えだけでは意図通りに動かず複雑なモーションが困難であることなどがあげられます。