Bootstrap4のハンバーガーメニューをカスタマイズしてアニメーションを付ける

Bootstrap4のハンバーガーメニューをカスタマイズしてアニメーションを付ける

Bootstrap4のnavbarで設置できるハンバーガーメニューを今風にアニメーションさせたくてカスタマイズさせました。

完成形

こんな感じです。

See the Pen navbar hamburger animation by itouoti12 (@itouoti12) on CodePen.

ハンバーガーメニューをクリックすると、3本線がくるっと回転して「✕」マークになります。

Bootstrapの設定

bootstrapのバージョンは4.3.1を使用しています。

    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">

    <!-- Bootstrap CSS -->
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css"
        integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">

    <!-- jQuery first, then Popper.js, then Bootstrap JS -->
    <script src="https://code.jquery.com/jquery-3.3.1.min.js"
        integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=" crossorigin="anonymous"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js"
        integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1"
        crossorigin="anonymous"></script>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js"
        integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM"
        crossorigin="anonymous"></script>

navbarを設定する

まずはプレーンなナビゲーションバーを設置してみます。
この時点では特にカスタムはしてないです。

    <nav class="navbar navbar-expand-md fixed-top navbar-light bg-light">
        <a class="navbar-brand" href="#">
          ナビゲーションバーのハンバーガーメニューにアニメーションを付与する
        </a>
        <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNav"
            aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
            <span class="navbar-toggler-icon"></span>
        </button>
        <div class="collapse navbar-collapse" id="navbarNav">
            <ul class="navbar-nav ml-auto">
                <li class="nav-item">
                    <a class="nav-link" href="#">page1</a>
                </li>
                <li class="nav-item">
                    <a class="nav-link" href="#">page2</a>
                </li>
                <li class="nav-item">
                    <a class="nav-link" href="#">page3</a>
                </li>
            </ul>
        </div>
    </nav>

するとウィンドウを縮小した時にハンバーガーメニューは以下のようになります。デフォルトです。

メニューを開く前

メニューを開いた後

そしてこれから以下の箇所をカスタマイズしていきます。

  • メニューアイコンの外枠の線を消す
  • メニューアイコンを押した後の選択動作を消す(青枠)
  • アイコンの中の三本線をアニメーションさせる

メニューアイコンの外枠の線を消す

cssでbootstrapのクラスを拡張し、border-colorのopacityを0にして消します。

.navbar-light .navbar-toggler {
  border-color: rgba(0, 0, 0, 0);
}

消えました。

メニューアイコンを押した後の選択動作を消す(青枠)

cssでbootstrapのクラスを拡張し、outline:noneを付与して消します。

.navbar-light .navbar-toggler {
  border-color: rgba(0, 0, 0, 0);
  outline: none;
}

消えました。

アイコンの中の三本線をアニメーションさせる

ここからが本番です。

まず元々のBootstrap上での3本線はどうなっているかというと、background-imageで設定されています。
つまりimageとして表示しているものになるので、このままだと線一つ一つに動きをつけることができません。
なので、一旦元々描画されている3本線を消しつつ、上から線を1本ずつ再描画させるようにします。

まずはHTMLでspanタグを3つ挿入します。

        <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNav"
            aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
            <span class="navbar-toggler-icon">
                <span></span>
                <span></span>
                <span></span>
            </span>
        </button>

次にcss上で元々のbackground-imageを消しつつ、線を引いていきます。

.navbar-light .navbar-toggler {
  border-color: rgba(0, 0, 0, 0);
  outline: none;
}

.navbar-light .navbar-toggler-icon {
  background-image: none;
}

.navbar-toggler-icon {
  position: relative;
  width: 40px;
  height: 40px;
  background: none;
  appearance: none;
  cursor: pointer;

  &,
  span {
    display: inline-block;
    box-sizing: border-box;
  }

  span {
    position: absolute;
    left: 5px;
    width: 80%;
    height: 2px;
    background-color: rgba(165, 165, 165, 1);
    border-radius: 1px;

    &:nth-of-type(1) {
      top: 8px;
    }
    &:nth-of-type(2) {
      top: 20px;
    }
    &:nth-of-type(3) {
      top: 32px;
    }
  }
}

再描画したメニューがこちらになります。

メニューを開いたとき

違和感なく描画できているのではないでしょうか。

そしてここからアニメーションをつけていきます。
transition,transform,opacityを駆使して動きを持たせます。
アニメーションについては下の参考リンクで飛んだ先のサイトにレパートリーがあるので見てみてください。

.navbar-light .navbar-toggler {
  border-color: rgba(0, 0, 0, 0);
  outline: none;
}

.navbar-light .navbar-toggler-icon {
  background-image: none;
}

.navbar-toggler-icon {
  position: relative;
  width: 40px;
  height: 40px;
  background: none;
  appearance: none;
  cursor: pointer;

  &,
  span {
    display: inline-block;
    transition: all 0.4s;
    box-sizing: border-box;
  }

  span {
    position: absolute;
    left: 5px;
    width: 80%;
    height: 2px;
    background-color: rgba(165, 165, 165, 1);
    border-radius: 1px;

    &:nth-of-type(1) {
      top: 8px;
    }
    &:nth-of-type(2) {
      top: 20px;
    }
    &:nth-of-type(3) {
      top: 32px;
    }
  }
}

.navbar-toggler {
  &:active {
    span.navbar-toggler-icon {
      span {
        &:nth-of-type(1) {
          transform: translateY(12px) rotate(-315deg);
        }
        &:nth-of-type(2) {
          opacity: 0;
        }
        &:nth-of-type(3) {
          transform: translateY(-12px) rotate(315deg);
        }
      }
    }
  }
}

これでアニメーションを適用することができました。
・・・ですが、このままだとボタンに対してクリックし続けている時にしか反応しません。
ナビゲーションバーが展開されても元の3本線に戻ってしまいます。
なので、ナビゲーションバーが展開された時にちゃんとアニメーションで変形後のアイコンになるようにしてあげないといけません。

Bootstrapのナビゲーションバーでの展開を制御している場所はどこか

bootstrapのナビゲーションバーの開閉の制御はaria-expanded属性のtrue/falseで制御されています。
chromeのデベロッパーツール等で動きを確認することができます。

展開前。aria-expandedがfalseとなっている。

展開後。aria-expandedがtrueとなっている。

よって、このaria-expanded属性の状態によってアニメーションの制御を行えばいいことがわかったので、cssを修正していきます。

.navbar-light .navbar-toggler {
  border-color: rgba(0, 0, 0, 0);
  outline: none;
}

.navbar-light .navbar-toggler-icon {
  background-image: none;
}

.navbar-toggler-icon {
  position: relative;
  width: 40px;
  height: 40px;
  background: none;
  appearance: none;
  cursor: pointer;

  &,
  span {
    display: inline-block;
    transition: all 0.4s;
    box-sizing: border-box;
  }

  span {
    position: absolute;
    left: 5px;
    width: 80%;
    height: 2px;
    background-color: rgba(165, 165, 165, 1);
    border-radius: 1px;

    &:nth-of-type(1) {
      top: 8px;
    }
    &:nth-of-type(2) {
      top: 20px;
    }
    &:nth-of-type(3) {
      top: 32px;
    }
  }
}

.navbar-toggler[aria-expanded='true'] {
  span.navbar-toggler-icon {
    span {
      &:nth-of-type(1) {
        transform: translateY(12px) rotate(-315deg);
      }
      &:nth-of-type(2) {
        opacity: 0;
      }
      &:nth-of-type(3) {
        transform: translateY(-12px) rotate(315deg);
      }
    }
  }
}

これで無事bootstrapのナビゲーションバーのカスタマイズができました。

参考リンク

CSSで実装するハンバーガーメニュークリック時のエフェクト 10+

【HTML・CSS】CSSでボタンをクリックしたときの枠線を消す方法

HTML5の独自データ属性にCSSを効かせる方法。

bootstrapカテゴリの最新記事