ハンバーガーメニューは「メニューだとわかりづらい」と言われることも多いですが、特にスマートフォンサイトなどでは実装する機会はやはり多くはなってきているので、今回はそのハンバーガーメニューをクリックした時(メニューが展開しているときなどのアクティブ時)のエフェクトをCSSで実装したサンプルをまとめました。
よく見る「×」のようなクローズボタンに変化するものから矢印に変化するものまで全12種類あります。

January 21, 2016 追記

共通のHTML・CSS

サンプルで使用しているHTMLとCSSは下記をベースとして使用しています。
スタイルの中には幅や高さを指定している部分やラインの色を指定している部分などあるので、紹介しているものを使用する場合はこれらを自身の環境に合わせて調整してください。

<button class="menu-trigger">
  <span></span>
  <span></span>
  <span></span>
</button>
.menu-trigger,
.menu-trigger span {
  display: inline-block;
  transition: all .4s;
  box-sizing: border-box;
}
.menu-trigger {
  position: relative;
  width: 50px;
  height: 44px;
  background: none;
  border: none;
  appearance: none;
  cursor: pointer;
}
.menu-trigger span {
  position: absolute;
  left: 0;
  width: 100%;
  height: 4px;
  background-color: #fff;
  border-radius: 4px;
}
.menu-trigger span:nth-of-type(1) {
  top: 0;
}
.menu-trigger span:nth-of-type(2) {
  top: 20px;
}
.menu-trigger span:nth-of-type(3) {
  bottom: 0;
}
  • 閲覧の際にChrome又はFirefoxで見てもらえるとほぼ問題なく動きの確認ができると思いますが、ブラウザによって動きや見栄えが説明と異なる場合があります。
  • 以下のサンプルでは、メニュークリック時にJavaScriptを使ってactiveというクラスが追加・削除する動きを実装していますので、それぞれサンプルのCSSもクリック後に.activeというクラスが追加される想定の記述となっています。

中央のラインが消え、上下のラインでクローズボタンに

クリックすると中央のラインがフェードアウトし、上下のラインがそれぞれ傾きクローズボタンになるものです。
クリック後のスタイルとしてCSSに下記を記述します。

.menu-trigger.active span:nth-of-type(1) {
  transform: translateY(20px) rotate(-45deg);
}
.menu-trigger.active span:nth-of-type(2) {
  opacity: 0;
}
.menu-trigger.active span:nth-of-type(3) {
  transform: translateY(-20px) rotate(45deg);
}

中央のラインが消え、上下のラインが回転しながらクローズボタンに

先ほどと同様にクリックすると中央のラインがフェードアウトし、上下のラインがそれぞれ傾きクローズボタンになるものですが、rotateの値を大きくすることでクルッと回転しながらクローズボタンの見栄えになる動きにできます。
クリック後のスタイルとしてCSSに下記を記述します。

.menu-trigger.active span:nth-of-type(1) {
  transform: translateY(20px) rotate(-315deg);
}
.menu-trigger.active span:nth-of-type(2) {
  opacity: 0;
}
.menu-trigger.active span:nth-of-type(3) {
  transform: translateY(-20px) rotate(315deg);
}

メニュー全体が回転しながらクローズボタンに #1

上で紹介してきたものと同じような感じでクリックするとひとつだけラインが消えて残りふたつのラインを傾けるという記述をしつつ、そこへさらにメニュー自体も回転するような記述を加えたものです。
クリック後のスタイルとしてCSSに下記を記述します。

.menu-trigger.active {
  transform: rotate(360deg);
}
.menu-trigger.active span:nth-of-type(1) {
  transform: translateY(20px) rotate(-45deg);
}
.menu-trigger.active span:nth-of-type(2) {
  transform: translateY(0) rotate(45deg);
}
.menu-trigger.active span:nth-of-type(3) {
  opacity: 0;
}

メニュー全体が回転しながらクローズボタンに #2

先ほどと同様にメニュー全体が回転するものですが、こちらはtransform: rotateXを使ったタイプで、クリック後のスタイルとしてCSSに下記を記述します。

.menu-trigger span:nth-of-type(3),
.menu-trigger.active span:nth-of-type(3) {
  transition: none;
}
.menu-trigger.active {
  transform: rotateX(720deg);
}
.menu-trigger.active span:nth-of-type(1) {
  transform: translateY(20px) rotate(-45deg);
}
.menu-trigger.active span:nth-of-type(2) {
  transform: translateY(0) rotate(45deg);
}
.menu-trigger.active span:nth-of-type(3) {
  opacity: 0;
}

ちなみに、iPhoneでMobile Safariで確認する際にメニューが消えてしまう場合は、その親となる要素にCSSでperspectiveを指定することで消えてしまうのを回避できます。

中央ラインの位置がずれながら消えていく

基本的には「1. 中央のラインが消え、上下のラインでクローズボタンに」の動きと同じですが、そこへさらに中央ライン位置が横にずれる動きを加えたものです。
サンプルは中央のラインが右にずれながら消えるというもので、クリック後のスタイルとしてCSSに下記を記述します。

.menu-trigger.active span:nth-of-type(1) {
  transform: translateY(20px) rotate(-45deg);
}
.menu-trigger.active span:nth-of-type(2) {
  left: 50%;
  opacity: 0;
  animation: active-menu-bar02 .8s forwards;
}
@keyframes active-menu-bar02 {
  100% {
    height: 0;
  }
}
.menu-trigger.active span:nth-of-type(3) {
  transform: translateY(-20px) rotate(45deg);
}

このサンプルコードでは消えていく中央ラインがクリックできるのを防ぐためにspan:nth-of-type(2)の動きの一部にanimationを用いていますが、Chromeであればanimationを使用せずにz-index: -1を記述すれば同じ見た目を実装できます。

中央ラインが飛んでいく

基本的な動きは「5. 中央ラインの位置がずれながら消えていく」の動きと同じ中央ライン位置が横にずれる動きになりますが、それを少しいじって飛んでいくような動きにしたものです。
クリック後のスタイルとしてCSSに下記を記述します。

.menu-trigger.active span:nth-of-type(1) {
  transform: translateY(20px) rotate(-45deg);
}
.menu-trigger.active span:nth-of-type(2) {
  left: 200%;
  opacity: 0;
  transform: translateY(10px);
  animation: active-menu-bar02 .8s forwards;
}
@keyframes active-menu-bar02 {
  100% {
    height: 0;
  }
}
.menu-trigger.active span:nth-of-type(3) {
  transform: translateY(-20px) rotate(45deg);
}

このサンプルコードでは消えていく中央ラインがクリックできるのを防ぐためにspan:nth-of-type(2)の動きの一部にanimationを用いていますが、Chromeであればanimationを使用せずにz-index: -1を記述すれば同じ見た目を実装できます。

ラインがひとつになり、その後クローズボタンに

クリックするとまず上下のラインが中央に移動して見た目がひとつのラインになり、その後クローズボタンに変化するというものです。
実装には共通のスタイルに加え、CSSに下記を記述します。

.menu-trigger span:nth-of-type(1) {
  animation: menu-bar01 .75s forwards;
}
@keyframes menu-bar01 {
  0% {
    transform: translateY(20px) rotate(45deg);
  }
  50% {
    transform: translateY(20px) rotate(0);
  }
  100% {
    transform: translateY(0) rotate(0);
  }
}
.menu-trigger span:nth-of-type(2) {
  transition: all .25s .25s;
  opacity: 1;
}
.menu-trigger span:nth-of-type(3) {
  animation: menu-bar02 .75s forwards;
}
@keyframes menu-bar02 {
  0% {
    transform: translateY(-20px) rotate(-45deg);
  }
  50% {
    transform: translateY(-20px) rotate(0);
  }
  100% {
    transform: translateY(0) rotate(0);
  }
}
.menu-trigger.active span:nth-of-type(1) {
  animation: active-menu-bar01 .75s forwards;
}
@keyframes active-menu-bar01 {
  0% {
    transform: translateY(0) rotate(0);
  }
  50% {
    transform: translateY(20px) rotate(0);
  }
  100% {
    transform: translateY(20px) rotate(45deg);
  }
}
.menu-trigger.active span:nth-of-type(2) {
  opacity: 0;
}
.menu-trigger.active span:nth-of-type(3) {
  animation: active-menu-bar03 .75s forwards;
}
@keyframes active-menu-bar03 {
  0% {
    transform: translateY(0) rotate(0);
  }
  50% {
    transform: translateY(-20px) rotate(0);
  }
  100% {
    transform: translateY(-20px) rotate(-45deg);
  }
}

上下のラインを動かして矢印に

横からスライドしてくるナビゲーションを実装しているサイトなどで見かけることがある、ハンバーガーから矢印へと変化するものです。
クリック後のスタイルとしてCSSに下記を記述します。

.menu-trigger.active span:nth-of-type(1),
.menu-trigger.active span:nth-of-type(3) {
  width: 20px;
}
.menu-trigger.active span:nth-of-type(1) {
  transform: translate(-1px,13px) rotate(-45deg);
}
.menu-trigger.active span:nth-of-type(3) {
  transform: translate(-1px,-13px) rotate(45deg);
}

回転しながら矢印に

先ほどのハンバーガーから矢印へと変化するものに回転の動きを加えたものです。
記述もほぼ同じで、クリック後のスタイルとしてCSSに下記を記述します。

.menu-trigger.active {
  transform: rotate(360deg);
}
.menu-trigger.active span:nth-of-type(1),
.menu-trigger.active span:nth-of-type(3) {
  width: 20px;
}
.menu-trigger.active span:nth-of-type(1) {
  transform: translate(-1px,13px) rotate(-45deg);
}
.menu-trigger.active span:nth-of-type(3) {
  transform: translate(-1px,-13px) rotate(45deg);
}

メニューボタンの向きを変える

こちらはクローズボタンや矢印になるものではなく、たまに実装しているサイトを見かけることもあるボタンが縦向きに変更するものです。
クリック後のスタイルとしてCSSに下記を記述し、見ての通りtransform: rotateで90度回転させるだけです。

.menu-trigger.active {
  transform: rotate(90deg);
}

クローズボタン変形前に波紋エフェクトを加える

基本的には「1. 中央のラインが消え、上下のラインでクローズボタンに」の動きと同じですが、その動きの前に波紋のようなエフェクトを加えたものです。
実装には共通のスタイルに加え、CSSに下記を記述します。

.menu-trigger span:nth-of-type(1) {
  animation: menu-bar01 .5s forwards;
}
@keyframes menu-bar01 {
  0% {
    transform: translateY(20px) rotate(-45deg);
  }
  100% {
    transform: translateY(0) rotate(0);
  }
}
.menu-trigger span:nth-of-type(2) {
  animation: menu-bar02 .5s forwards;
}
@keyframes menu-bar02 {
  0% {
    opacity: 0;
  }
  100% {
    opacity: 1;
  }
}
.menu-trigger span:nth-of-type(3) {
  animation: menu-bar03 .5s forwards;
}
@keyframes menu-bar03 {
  0% {
    transform: translateY(-20px) rotate(45deg);
  }
  100% {
    transform: translateY(0) rotate(0);
  }
}
.menu-trigger::after {
  position: absolute;
  top: 50%;
  left: 50%;
  display: block;
  content: '';
  width: 30px;
  height: 30px;
  margin: -16px 0 0 -16px;
  border-radius: 50%;
  border: 1px solid rgba(255, 255, 255, .3);
  transition: all .1s;
  opacity: 0;
}
.menu-trigger.active::after {
  animation: circle .5s;
}
@keyframes circle {
  0% {
    transform: scale(.1);
    opacity: 0;
  }
  50% {
    opacity: 1;
  }
  100% {
    transform: scale(3.5);
    opacity: 0;
  }
}
.menu-trigger.active span:nth-of-type(1) {
  animation: active-menu-bar01 .5s .5s forwards;
}
@keyframes active-menu-bar01 {
  0% {
    transform: translateY(0) rotate(0);
  }
  100% {
    transform: translateY(20px) rotate(-45deg);
  }
}
.menu-trigger.active span:nth-of-type(2) {
  animation: active-menu-bar02 .5s .5s forwards;
}
@keyframes active-menu-bar02 {
  0% {
    opacity: 1;
  }
  100% {
    opacity: 0;
  }
}
.menu-trigger.active span:nth-of-type(3) {
  animation: active-menu-bar03 .5s .5s forwards;
}
@keyframes active-menu-bar03 {
  0% {
    transform: translateY(0) rotate(0);
  }
  100% {
    transform: translateY(-20px) rotate(45deg);
  }
}

中央ラインがサークルに変形するような見た目

実際には同じ要素を使っているわけではないですが、「5. 中央ラインの位置がずれながら消えていく」の動きをしつつ、そこに擬似要素を使ってその中央ラインがサークルになっていくような見た目にしたものです。
実装には共通のスタイルに加え、CSSに下記を記述します。

.menu-trigger::after {
  position: absolute;
  top: 50%;
  left: 50%;
  display: block;
  content: '';
  width: 84px;
  height: 84px;
  margin: -45px 0 0 -45px;
  border-radius: 50%;
  border: 4px solid transparent;
  transition: all .75s;
}
.menu-trigger.active span:nth-of-type(1) {
  transform: translateY(20px) rotate(-45deg);
}
.menu-trigger.active span:nth-of-type(2) {
  left: 60%;
  opacity: 0;
  animation: active-menu-bar02 .8s forwards;
}

@keyframes active-menu-bar02 {
  100% {
    height: 0;
  }
}
.menu-trigger.active span:nth-of-type(3) {
  transform: translateY(-20px) rotate(45deg);
}
.menu-trigger.active::after {
  animation: circle .4s .25s forwards;
}
@keyframes circle {
  0% {
    border-color: transparent;
    transform: rotate(0);
  }
  25% {
    border-color: transparent #fff transparent transparent;
  }
  50% {
    border-color: transparent #fff #fff transparent;
  }
  75% {
    border-color: transparent #fff #fff #fff;
  }
  100% {
    border-color: #fff;
    transform: rotate(-680deg);
  }
}

サークルを表現するために擬似要素を作成し、まずはそこでborder-colortransparentを指定しておきます。
あとはクリック(クラスが付加)されたタイミングでそれぞれのborderにひとつずつカラー指定される動きをanimationで指定しつつtransform: rotateで回転させることでこのような見た目になります。
ちなみに今回はCSSだけで実装ということでこのようにborderを用いてやってみましたが、普通にサークル部分はSVG使ってやったりした方が全然綺麗に実装できます...。


上で紹介した動きをまとめて確認したい場合は以下でご覧になれます。

また、他のエフェクトとしていずれもここでは紹介していないものを以下で紹介しているので、興味ある方は併せてご覧ください。