【CSS】ハンバーガーメニュー実装サンプル集(クリック時のエフェクトも集めました)

きのこさん
ん、ハンバーガー?
きのこさん
三本線がハンバーガーに見えるからってことらしいですよ

クリックエフェクト サンプル集

いろんなハンバーガーメニューのクリック時のエフェクトを作ってみる。
動きがわかりやすいようにゆっくり動くように指定。
スピードを変えたいときは、transitionを変更する。

ボタンを押すと形が変わって、もう一度押すと、もとに戻ります。
(2026年10月に、見本を新しくしました)

HTML は、ボタン1つ分です。id を btn01〜btn19 に変えると、それぞれの動きになります。04 だけは、ボタンの親に perspective: 1000px; を付けてください。

コードを見る(HTML・CSS・JavaScript)

HTML

<button class="btn-trigger" id="btn01" aria-label="メニュー">
  <span></span>
  <span></span>
  <span></span>
</button>

CSS

/*=============================
.btn-trigger(共通)
=============================*/
.btn-trigger {
  position: relative;
  width: 50px;
  height: 44px;
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
}
.btn-trigger span {
  position: absolute;
  left: 0;
  width: 100%;
  height: 4px;
  background-color: #2b2a27;
  border-radius: 4px;
}
.btn-trigger,
.btn-trigger span {
  display: inline-block;
  transition: all .5s;
  box-sizing: border-box;
}
.btn-trigger span:nth-of-type(1) { top: 0; }
.btn-trigger span:nth-of-type(2) { top: 20px; }
.btn-trigger span:nth-of-type(3) { bottom: 0; }

@keyframes bar-hide { 100% { height: 0; } }

/* 01 */
#btn01.active span:nth-of-type(1) { transform: translateY(20px) rotate(-45deg); }
#btn01.active span:nth-of-type(2) { opacity: 0; }
#btn01.active span:nth-of-type(3) { transform: translateY(-20px) rotate(45deg); }

/* 02 */
#btn02.active span:nth-of-type(1) { transform: translateY(20px) rotate(45deg); }
#btn02.active span:nth-of-type(2) { opacity: 0; }
#btn02.active span:nth-of-type(3) { transform: translateY(-20px) rotate(-45deg); }

/* 03 */
#btn03.active { transform: rotate(360deg); }
#btn03.active span:nth-of-type(1) { transform: translateY(20px) rotate(-45deg); }
#btn03.active span:nth-of-type(2) { transform: translateY(0) rotate(45deg); }
#btn03.active span:nth-of-type(3) { opacity: 0; }

/* 04(親に perspective: 1000px) */
#btn04 span:nth-of-type(3) { transition: none; }
#btn04.active { transform: rotateX(720deg); }
#btn04.active span:nth-of-type(1) { transform: translateY(20px) rotate(-45deg); }
#btn04.active span:nth-of-type(2) { transform: translateY(0) rotate(45deg); }
#btn04.active span:nth-of-type(3) { opacity: 0; }

/* 05 */
#btn05.active span:nth-of-type(1) { transform: translateY(20px) rotate(-45deg); }
#btn05.active span:nth-of-type(2) { left: 50%; opacity: 0; animation: bar-hide .8s forwards; }
#btn05.active span:nth-of-type(3) { transform: translateY(-20px) rotate(45deg); }

/* 06 */
#btn06.active span:nth-of-type(1) { transform: translateY(20px) rotate(-45deg); }
#btn06.active span:nth-of-type(2) { left: 200%; opacity: 0; transform: translateY(10px); animation: bar-hide .8s forwards; }
#btn06.active span:nth-of-type(3) { transform: translateY(-20px) rotate(45deg); }

/* 07(下がってから回る) */
#btn07 span:nth-of-type(1) { animation: btn07-bar01 .75s forwards; }
#btn07 span:nth-of-type(2) { transition: all .25s .25s; opacity: 1; }
#btn07 span:nth-of-type(3) { animation: btn07-bar03 .75s forwards; }
#btn07.active span:nth-of-type(1) { animation: active-btn07-bar01 .75s forwards; }
#btn07.active span:nth-of-type(2) { opacity: 0; }
#btn07.active span:nth-of-type(3) { animation: active-btn07-bar03 .75s forwards; }
@keyframes btn07-bar01 {
  0%   { transform: translateY(20px) rotate(45deg); }
  50%  { transform: translateY(20px) rotate(0); }
  100% { transform: translateY(0) rotate(0); }
}
@keyframes btn07-bar03 {
  0%   { transform: translateY(-20px) rotate(-45deg); }
  50%  { transform: translateY(-20px) rotate(0); }
  100% { transform: translateY(0) rotate(0); }
}
@keyframes active-btn07-bar01 {
  0%   { transform: translateY(0) rotate(0); }
  50%  { transform: translateY(20px) rotate(0); }
  100% { transform: translateY(20px) rotate(45deg); }
}
@keyframes active-btn07-bar03 {
  0%   { transform: translateY(0) rotate(0); }
  50%  { transform: translateY(-20px) rotate(0); }
  100% { transform: translateY(-20px) rotate(-45deg); }
}

/* 08 */
#btn08.active span:nth-of-type(1) { transform: translateY(20px) rotate(-315deg); }
#btn08.active span:nth-of-type(2) { opacity: 0; }
#btn08.active span:nth-of-type(3) { transform: translateY(-20px) rotate(315deg); }

/* 09 */
#btn09.active span:nth-of-type(1) { transform: translateY(20px) rotate(315deg); }
#btn09.active span:nth-of-type(2) { opacity: 0; }
#btn09.active span:nth-of-type(3) { transform: translateY(-20px) rotate(-315deg); }

/* 10・11・12(ボタンごと回る) */
#btn10.active { transform: rotate(-90deg); }
#btn11.active { transform: rotate(90deg); }
#btn12.active { transform: rotate(450deg); }

/* 13・14(左向きの矢印) */
#btn14.active { transform: rotate(360deg); }
#btn13.active span:nth-of-type(1), #btn13.active span:nth-of-type(3),
#btn14.active span:nth-of-type(1), #btn14.active span:nth-of-type(3) { width: 20px; }
#btn13.active span:nth-of-type(1), #btn14.active span:nth-of-type(1) { transform: translate(-1px, 13px) rotate(-45deg); }
#btn13.active span:nth-of-type(3), #btn14.active span:nth-of-type(3) { transform: translate(-1px, -13px) rotate(45deg); }

/* 15・16(右向きの矢印) */
#btn16.active { transform: rotate(-360deg); }
#btn15.active span:nth-of-type(1), #btn15.active span:nth-of-type(3),
#btn16.active span:nth-of-type(1), #btn16.active span:nth-of-type(3) { width: 20px; }
#btn15.active span:nth-of-type(1), #btn16.active span:nth-of-type(1) { transform: translate(31px, 13px) rotate(45deg); }
#btn15.active span:nth-of-type(3), #btn16.active span:nth-of-type(3) { transform: translate(31px, -13px) rotate(-45deg); }

/* 17(まるが出る) */
#btn17::after,
#btn19::after {
  content: '';
  position: absolute;
  top: 50%;
  left: 50%;
  display: block;
  width: 84px;
  height: 84px;
  margin: -45px 0 0 -45px;
  border-radius: 50%;
  border: 4px solid transparent;
  transition: all .75s;
}
#btn17.active span:nth-of-type(1) { transform: translateY(20px) rotate(45deg); }
#btn17.active span:nth-of-type(2) { left: 60%; opacity: 0; animation: bar-hide .8s forwards; }
#btn17.active span:nth-of-type(3) { transform: translateY(-20px) rotate(-45deg); }
#btn17.active::after { border-color: #2b2a27; }

/* 18(波紋のあとに ×) */
#btn18 span:nth-of-type(1) { animation: btn18-bar01 .5s forwards; }
#btn18 span:nth-of-type(2) { animation: btn18-bar02 .5s forwards; }
#btn18 span:nth-of-type(3) { animation: btn18-bar03 .5s forwards; }
#btn18::after {
  content: '';
  position: absolute;
  top: 50%;
  left: 50%;
  display: block;
  width: 30px;
  height: 30px;
  margin: -16px 0 0 -16px;
  border-radius: 50%;
  border: 1px solid rgba(43, 42, 39, .4);
  opacity: 0;
}
#btn18.active::after { animation: circle .5s; }
#btn18.active span:nth-of-type(1) { animation: active-btn18-bar01 .5s .5s forwards; }
#btn18.active span:nth-of-type(2) { animation: active-btn18-bar02 .5s .5s forwards; }
#btn18.active span:nth-of-type(3) { animation: active-btn18-bar03 .5s .5s forwards; }
@keyframes btn18-bar01 { 0% { transform: translateY(20px) rotate(-45deg); } 100% { transform: translateY(0) rotate(0); } }
@keyframes btn18-bar02 { 0% { opacity: 0; } 100% { opacity: 1; } }
@keyframes btn18-bar03 { 0% { transform: translateY(-20px) rotate(45deg); } 100% { transform: translateY(0) rotate(0); } }
@keyframes active-btn18-bar01 { 0% { transform: translateY(0) rotate(0); } 100% { transform: translateY(20px) rotate(-45deg); } }
@keyframes active-btn18-bar02 { 0% { opacity: 1; } 100% { opacity: 0; } }
@keyframes active-btn18-bar03 { 0% { transform: translateY(0) rotate(0); } 100% { transform: translateY(-20px) rotate(45deg); } }
@keyframes circle {
  0%   { transform: scale(.1); opacity: 0; }
  50%  { opacity: 1; }
  100% { transform: scale(3.5); opacity: 0; }
}

/* 19(まるを描きながら回る) */
#btn19.active span:nth-of-type(1) { transform: translateY(20px) rotate(-45deg); }
#btn19.active span:nth-of-type(2) { left: 60%; opacity: 0; animation: bar-hide .8s forwards; }
#btn19.active span:nth-of-type(3) { transform: translateY(-20px) rotate(45deg); }
#btn19.active::after { animation: active-btn19 .7s .25s forwards; }
@keyframes active-btn19 {
  0%   { border-color: transparent; transform: rotate(0); }
  25%  { border-color: transparent #2b2a27 transparent transparent; }
  50%  { border-color: transparent #2b2a27 #2b2a27 transparent; }
  75%  { border-color: transparent #2b2a27 #2b2a27 #2b2a27; }
  100% { border-color: #2b2a27; transform: rotate(-680deg); }
}

/* 動きを減らす設定のとき:すぐに切り替える */
@media (prefers-reduced-motion: reduce) {
  .btn-trigger, .btn-trigger span, .btn-trigger::after {
    transition-duration: .01ms !important;
    animation-duration: .01ms !important;
    animation-delay: 0s !important;
  }
}

JavaScript

document.querySelectorAll('.btn-trigger').forEach(btn => {
  btn.addEventListener('click', () => btn.classList.toggle('active'));
});

実装サンプル 左上にボタンがあるタイプ

ボタンを押すと、左からメニューが出てきます。うしろは少し暗くなって、暗いところを押しても閉じます。
閉じているあいだは、三本線の長さがゆらゆら動きます。

コードを見る(HTML・CSS・JavaScript)

HTML

<div id="navArea">
  <nav>
    <ul>
      <li><a href="#"><span>01</span>デザインのメモ</a></li>
      <li><a href="#"><span>02</span>works</a></li>
      <li><a href="#"><span>03</span>service</a></li>
      <li><a href="#"><span>04</span>contact</a></li>
    </ul>
  </nav>
  <button class="toggle_btn" aria-label="メニュー" aria-expanded="false">
    <span></span><span></span><span></span>
  </button>
  <div id="mask"></div>
</div>

CSS

/* ===== 左上にボタンがあるタイプ ===== */

/* メニュー(左から出る) */
#navArea nav {
  position: fixed;
  top: 0;
  left: 0;
  z-index: 3;
  width: 300px;
  height: 100%;
  padding: 96px 32px 32px;
  background: #2b2a27;
  color: #fff;
  transform: translateX(-100%);
  transition: transform .5s;
}
#navArea.open nav { transform: translateX(0); }
#navArea nav li { border-bottom: 1px solid rgba(255, 255, 255, .16); }
#navArea nav a { display: flex; align-items: baseline; gap: 16px; padding: 16px 0; }
#navArea nav a span { font-size: 12px; color: #e8dc6a; }

/* うしろを暗くする */
#mask {
  position: fixed;
  inset: 0;
  z-index: 2;
  background: rgba(43, 42, 39, .5);
  opacity: 0;
  visibility: hidden;
  transition: .5s;
}
#navArea.open #mask { opacity: 1; visibility: visible; }

/* ボタン */
.toggle_btn {
  position: fixed;
  top: 16px;
  left: 16px;
  z-index: 4;
  width: 48px;
  height: 48px;
  border: 0;
  border-radius: 50%;
  background: #e8dc6a;
  cursor: pointer;
}
.toggle_btn span {
  position: absolute;
  left: 14px;
  width: 20px;
  height: 2px;
  border-radius: 2px;
  background: #2b2a27;
  transition: .5s;
  animation: wave 1.6s infinite; /* 閉じているあいだ、長さがゆれる */
}
.toggle_btn span:nth-child(1) { top: 17px; }
.toggle_btn span:nth-child(2) { top: 23px; animation-delay: .2s; }
.toggle_btn span:nth-child(3) { top: 29px; animation-delay: .4s; }
@keyframes wave { 50% { width: 12px; } }

/* 開いたら × に */
#navArea.open .toggle_btn span { animation: none; }
#navArea.open .toggle_btn span:nth-child(1) { transform: translateY(6px) rotate(-45deg); }
#navArea.open .toggle_btn span:nth-child(2) { opacity: 0; }
#navArea.open .toggle_btn span:nth-child(3) { transform: translateY(-6px) rotate(45deg); }

@media (max-width: 600px) {
  #navArea nav { width: 240px; padding: 88px 24px 24px; }
}
@media (prefers-reduced-motion: reduce) {
  #navArea * { transition: none !important; animation: none !important; }
}

JavaScript

const nav  = document.getElementById('navArea');
const btn  = nav.querySelector('.toggle_btn');
const mask = document.getElementById('mask');

btn.addEventListener('click', () => {
  const isOpen = nav.classList.toggle('open');
  btn.setAttribute('aria-expanded', isOpen);
});
mask.addEventListener('click', () => {
  nav.classList.remove('open');
  btn.setAttribute('aria-expanded', false);
});

実装サンプル 右上にボタンがあるタイプ

ボタンは右上、メニューも右から出てきます。開くと、三本線がくるっと回って × になります。

コードを見る(HTML・CSS・JavaScript)

HTML

<div id="navArea">
  <nav>
    <ul>
      <li><a href="#"><span>01</span>デザインのメモ</a></li>
      <li><a href="#"><span>02</span>works</a></li>
      <li><a href="#"><span>03</span>service</a></li>
      <li><a href="#"><span>04</span>contact</a></li>
    </ul>
  </nav>
  <button class="toggle_btn" aria-label="メニュー" aria-expanded="false">
    <span></span><span></span><span></span>
  </button>
  <div id="mask"></div>
</div>

CSS

/* ===== 右上にボタンがあるタイプ ===== */

/* メニュー(右から出る) */
#navArea nav {
  position: fixed;
  top: 0;
  right: 0;
  z-index: 3;
  width: 300px;
  height: 100%;
  padding: 96px 32px 32px;
  background: #e8dc6a;
  transform: translateX(100%);
  transition: transform .5s;
}
#navArea.open nav { transform: translateX(0); }
#navArea nav li { border-bottom: 1px solid rgba(43, 42, 39, .2); }
#navArea nav a { display: flex; align-items: baseline; gap: 16px; padding: 16px 0; }
#navArea nav a span { font-size: 12px; }

/* うしろを暗くする */
#mask {
  position: fixed;
  inset: 0;
  z-index: 2;
  background: rgba(43, 42, 39, .5);
  opacity: 0;
  visibility: hidden;
  transition: .5s;
}
#navArea.open #mask { opacity: 1; visibility: visible; }

/* ボタン */
.toggle_btn {
  position: fixed;
  top: 16px;
  right: 16px;
  z-index: 4;
  width: 48px;
  height: 48px;
  border: 0;
  border-radius: 50%;
  background: #2b2a27;
  cursor: pointer;
}
.toggle_btn span {
  position: absolute;
  left: 14px;
  width: 20px;
  height: 2px;
  border-radius: 2px;
  background: #fff;
  transition: .5s;
}
.toggle_btn span:nth-child(1) { top: 17px; }
.toggle_btn span:nth-child(2) { top: 23px; }
.toggle_btn span:nth-child(3) { top: 29px; }

/* 開いたら、くるっと回って × に */
#navArea.open .toggle_btn span:nth-child(1) { transform: translateY(6px) rotate(-315deg); }
#navArea.open .toggle_btn span:nth-child(2) { opacity: 0; }
#navArea.open .toggle_btn span:nth-child(3) { transform: translateY(-6px) rotate(315deg); }

@media (max-width: 600px) {
  #navArea nav { width: 240px; padding: 88px 24px 24px; }
}
@media (prefers-reduced-motion: reduce) {
  #navArea * { transition: none !important; }
}

JavaScript

const nav  = document.getElementById('navArea');
const btn  = nav.querySelector('.toggle_btn');
const mask = document.getElementById('mask');

btn.addEventListener('click', () => {
  const isOpen = nav.classList.toggle('open');
  btn.setAttribute('aria-expanded', isOpen);
});
mask.addEventListener('click', () => {
  nav.classList.remove('open');
  btn.setAttribute('aria-expanded', false);
});

実装サンプル 左上にボタンがあって全体に移動するタイプ

メニューと一緒に、ページ全体が右へずれます。開くと、ボタンは ← の形になります。
ページの中身を .page で囲んで、#navArea のすぐあとに置いてください。

コードを見る(HTML・CSS・JavaScript)

HTML

<div id="navArea">
  <nav>
    <ul>
      <li><a href="#"><span>01</span>デザインのメモ</a></li>
      <li><a href="#"><span>02</span>works</a></li>
      <li><a href="#"><span>03</span>service</a></li>
      <li><a href="#"><span>04</span>contact</a></li>
    </ul>
  </nav>
  <button class="toggle_btn" aria-label="メニュー" aria-expanded="false">
    <span></span><span></span><span></span>
  </button>
  <div id="mask"></div>
</div>

<div class="page">
  <!-- ページの中身 -->
</div>

CSS

/* ===== ページごと横にずれるタイプ ===== */
body { overflow-x: hidden; }

/* メニュー(ページのうしろに置いておく) */
#navArea nav {
  position: fixed;
  top: 0;
  left: 0;
  z-index: 1;
  width: 300px;
  height: 100%;
  padding: 96px 32px 32px;
  background: #f3efe6;
}
#navArea nav li { border-bottom: 1px solid #e8e3d8; }
#navArea nav a { display: flex; align-items: baseline; gap: 16px; padding: 16px 0; }
#navArea nav a span { font-size: 12px; color: #6b675f; }

/* ページ・ボタン・マスクが一緒に右へ動く */
.page { position: relative; z-index: 2; transition: transform .5s; }
#mask {
  position: fixed;
  inset: 0;
  z-index: 3;
  background: rgba(43, 42, 39, .15);
  opacity: 0;
  visibility: hidden;
  transition: .5s;
}
#navArea.open ~ .page,
#navArea.open #mask,
#navArea.open .toggle_btn { transform: translateX(300px); }
#navArea.open #mask { opacity: 1; visibility: visible; }

/* ボタン */
.toggle_btn {
  position: fixed;
  top: 16px;
  left: 16px;
  z-index: 4;
  width: 48px;
  height: 48px;
  border: 0;
  border-radius: 50%;
  background: #e8dc6a;
  cursor: pointer;
  transition: transform .5s;
}
.toggle_btn span {
  position: absolute;
  left: 14px;
  width: 20px;
  height: 2px;
  border-radius: 2px;
  background: #2b2a27;
  transform-origin: left center;
  transition: .5s;
}
.toggle_btn span:nth-child(1) { top: 17px; }
.toggle_btn span:nth-child(2) { top: 23px; }
.toggle_btn span:nth-child(3) { top: 29px; }

/* 開いたら ← に(上下の線が短くなって、矢じりになる) */
#navArea.open .toggle_btn span:nth-child(1) { width: 10px; transform: translateY(6px) rotate(-45deg); }
#navArea.open .toggle_btn span:nth-child(3) { width: 10px; transform: translateY(-6px) rotate(45deg); }

@media (max-width: 600px) {
  #navArea nav { width: 240px; padding: 88px 24px 24px; }
  #navArea.open ~ .page,
  #navArea.open #mask,
  #navArea.open .toggle_btn { transform: translateX(240px); }
}
@media (prefers-reduced-motion: reduce) {
  #navArea *, .page { transition: none !important; }
}

JavaScript

const nav  = document.getElementById('navArea');
const btn  = nav.querySelector('.toggle_btn');
const mask = document.getElementById('mask');

btn.addEventListener('click', () => {
  const isOpen = nav.classList.toggle('open');
  btn.setAttribute('aria-expanded', isOpen);
});
mask.addEventListener('click', () => {
  nav.classList.remove('open');
  btn.setAttribute('aria-expanded', false);
});

さいごに

きのこさん
いろいろありますねー
きのこさん
随時追加予定ですー

デザコトauthor

あ、いいな、と思うWebデザインを紹介しています。デザインの参考に。やさしいデザインが多いです。Webデザインギャラリー『デザインのこと - Web design gallery』を運営しています。