【特集一覧】最新ガジェットから独占取材まで!
オタクに捧ぐ公式Twitter、始動(告知バナー)

【SCSS】90行以下で綺麗なハンバーガーメニューを作ろう(解説あり)

この記事ではたった90行以下でハンバーガーメニューを作成するサンプルを解説とともにご紹介します。シンプルでありながらアニメーションもしっかり作られていますのでぜひお試し下さい。

サンプルコード

早速以下にサンプルのSCSSコードを紹介します。ぜひご参考しにして下さい。
デモページ(Live Demo)はこちら

HTML

<nav>
  <input id="menu__toggle" type="checkbox">
  <label class="menu__btn" for="menu__toggle">
    <span class="menu__btn__bar"></span>
  </label>
  <ul class="menu__content">
    <li>
      <a href="#top"><span>TOP</span></a>
    </li>
    <li>
      <a href="#"><span>NEWS</span></a>
    </li>
    <li>
      <a href="#"><span>ABOUT</span></a>
    </li>
    <li><a href="#"><span>CONTACT</span></a>
    </li>
  </ul>
</nav>

SCSS

// トランスパイルしないと動きません
#menu__toggle {
    opacity: 0;
    &:checked ~ {
        .menu__btn > span {
            transform: rotate(45deg);
            &::before {
                top: 0;
                transform: rotate(0);
            }
            &::after {
                top: 0;
                transform: rotate(90deg);
            }
        }
        .menu__content {
            visibility: visible;
            left: 0;
        }
    }
}

.menu__btn {
    display: flex;
    align-items: center;
    position: fixed;
    top: 20px;
    right: 20px;
    width: 26px;
    height: 26px;
    cursor: pointer;

    .menu__btn__bar {
        display: block;
        position: absolute;
        width: 100%;
        height: 2px;
        background-color: #616161;
        transition-duration: 0.25s;

        &::before,
        &::after {
            @extend .menu__btn__bar;
            content: "";
        }

        &::before {
            top: -8px;
           content: "";
        }

        &::after {
            top: 8px;
           content: "";
        }
    }
}

.menu__content {
    display: block;
    position: fixed;
    visibility: hidden;
    top: 0;
    left: -100%;
    width: 300px;
    height: 100%;
    margin: 0;
    padding: 80px 0;
    list-style: none;
    background-color: #eceff1;
    box-shadow: 1px 0px 6px rgba(0, 0, 0, 0.2);
    transition-duration: 0.25s;

    li {
        display: block;
        padding: 12px 24px;
        transition-duration: 0.25s;

        a {
            text-decoration: none;
            color: #222;
            font-size: 20px;
            font-weight: 600;
        }

        &:hover {
            background-color: #cfd8dc;
        }
    }
}

参考CodePen

以下のCodePenのデザインを参考に、手作業でScssに逆トランスパイルしました。製作者に感謝申し上げます。

仕組み・解説

それではハンバーガーメニューを構成するSCSSを解説します。

メニューボタンの表示・ロジック

「ハンバーガーメニューのボタン」はmenu__btn { }にて書かれています。

ハンバーガーメニューは3本線で構成されていますが、3本の線を.menu__btn__barと2つの疑似要素で使って作ります。

※span要素にmenu__btn__barクラスを指定せずとも、menu__btn > spanでも良い上に冗長化して見えるのですが@extendでスタイルの継承を行うためにクラス名を付与しています。
共通しているスタイルを継承することで管理をしやすく出来るのもSCSSの利点です。

また、疑似要素を上下8ピクセルずらすことで画像のようにできます。

メニュー表示/非表示の仕組み・アニメーション

メニューボタンを押したらコンテンツが表示される仕組みは#menu__toggle(input要素)に書かれています。

仕組みを単純に説明すると透明なチェックボックスを配置し、チェックがONならメニューコンテンツを表示&OFFなら非表示にすることで実現されています。

#menu__toggle {
    opacity: 0;
    &:checked ~ {
          ︙
        .menu__btn > span {
        .menu__content {
            visibility: visible;
            left: 0;
        }
    }
}

opacity: 0;なので透明

メニューボタンのアニメーションについては、チェック時には&:checked{ }の部分にあるSCSSが適用されます。その部分にて先程説明した疑似要素がアニメーションを設定します。

&:checked ~ {
    .menu__btn > span {
        transform: rotate(45deg);
        &::before {
            top: 0;
            transform: rotate(0);
        }
︙

rotate()で角度を指定することで
※&.checkedの「&」は親要素セレクタの事で、この場合は直前の親要素「#menu__toggle」を指します

メニューコンテンツの整形

最後にメニューコンテンツのレイアウトを行います。menu__contentクラスに記載されています。

リンクは全てリストで管理されていますので、bladeの@foreachやvueのv-forといったプログラム側からのマークアップにも簡単に対応できます。

余録

スマホでタップした時の”青いフィルタ”を消す

スマホでタップした際によく「タップした要素を示すフィルタ」が表示されます。ただ、メニュー表示ではデザインに影響するためフィルタを消すスタイルを紹介。

-webkit-tap-highlight-color: transparent;

上記スタイルを任意の要素に適用する事で非表示になります。ただ、すべての要素に適用させるとアクセシビリティ的に問題にもなるのでよく考えて指定するようにして下さい。

Live Sass Compilerで自動Minifyしたい!

VS CodeでリアルタイムにSass(Scss)をトランスパイルするLive Sass Compilerで出力結果をMinifyするには以下の設定を行うだけでできます。

VS CodeのconfigにあるliveSassCompiler.settings.formatsの部分のformatをcompressedに変更する。

以上ぜひお試し下さい。

コメント

タイトルとURLをコピーしました