中級

ボタンでメニューを開閉する(CSSのみ)

前回作った三本線のボタンに、右からスライドして出てくるメニューを組み合わせます。このレッスンで、CSSだけのハンバーガーメニューが完成します。

閉じている状態と、右からメニューが出てきた状態
ボタンを押すと、右からメニューが出てくる

手順1:メニューのHTMLを足す

label の後ろに、メニュー(nav)を足します。input → label → nav の順番に並べるのがポイントです。

  <header class="header">
    <a class="logo" href="#">Sample Cafe</a>
    <input type="checkbox" id="menu-btn">
    <label for="menu-btn" class="menu-toggle">
      <span></span>
      <span></span>
      <span></span>
    </label>
    <nav class="global-nav">
      <ul>
        <li><a href="#">HOME</a></li>
        <li><a href="#">コンセプト</a></li>
        <li><a href="#">メニュー</a></li>
        <li><a href="#">店舗案内</a></li>
        <li><a href="#">お問い合わせ</a></li>
      </ul>
    </nav>
  </header>

手順2:メニューを画面の外に隠しておく

メニューは、ふだんは画面の右の外側に置いておきます。position: fixed で画面に固定し、right: -100% で画面の幅ぶん右へ押し出します。

/* ---- メニュー本体:最初は画面の右外に隠しておく ---- */
.global-nav {
  position: fixed;
  top: 0;
  right: -100%;               /* 画面の外(右側)へ押し出す */
  width: 80%;
  max-width: 360px;
  height: 100vh;
  padding: 90px 30px 30px;
  background: #3b2a20;
  color: #fff;
  transition: right .4s;      /* 0.4秒かけてスライド */
  z-index: 10;
}
.global-nav a {
  display: block;
  padding: 14px 0;
  border-bottom: 1px solid rgba(255,255,255,.2);
}

height: 100vh は「画面の高さいっぱい」という意味です。vh は画面の高さを100等分した単位でしたね。

手順3:チェックが入ったら、メニューを画面の中へ

前回と同じく :checked ~ を使います。チェックが入ったら right を 0 にすると、メニューが画面の右端にぴったり収まります。transition を書いておいたので、0.4秒かけてスライドして出てきます。

/* ---- チェックが入ったらメニューを画面の中へ ---- */
#menu-btn:checked ~ .global-nav {
  right: 0;
}

手順4:ボタンをメニューより手前に出す

このままだと、出てきたメニューがボタンの上に重なって、ボタンが押せなくなります。ボタンに position: relative と z-index を付けて、メニューより手前に出します。メニューの背景が濃い色なので、開いたときは線を白にします。

/* ボタンはメニューより手前に。開いたら線を白に */
.menu-toggle {
  position: relative;
  z-index: 20;
}
#menu-btn:checked ~ .menu-toggle span {
  background: #fff;
}

z-index は重なりの順番で、数字が大きいほど手前に表示されます。メニューが10、ボタンが20なので、ボタンが手前です。くわしくはz-indexのレッスンで学びます。

「+」と「~」の違い

兄弟要素を指定する記号は2つあります。よく似ているので、ここで整理しておきましょう。

記号名前指定できる要素
A + B隣接兄弟結合子Aのすぐ後ろにある兄弟のBだけ
A ~ B一般兄弟結合子Aより後ろにある兄弟のBすべて

今回のHTMLは input → label → nav の順です。nav は input のすぐ後ろではないので、+ では届きません。だから ~ を使っています。

ほかの隠し方:display と animation

メニューを隠す方法は、画面の外へ押し出すだけではありません。display: none で消しておき、チェックが入ったら display: block にする方法もあります。この方法だと transition が効かないので、ふわっと出したいときは animation を使います。

nav {
  display: none;                /* ふだんは消しておく */
}
#menu-btn:checked ~ nav {
  display: block;               /* チェックが入ったら表示 */
  animation: fadeIn 1s;         /* 1秒かけてふわっと */
}
@keyframes fadeIn {
  from { opacity: 0; }
  to   { opacity: 1; }
}

CSSだけの方法の弱点

CSSだけでもメニューは動きますが、実際のサイトで使うには弱点もあります。

  • チェックボックスは本来、フォームの部品です。読み上げソフトを使う人に「メニューのボタン」だと伝わりにくくなります。
  • キーボードの Tab キーで、ボタンに移動できません。
  • メニューの中のリンク(同じページ内へのリンク)を押しても、メニューが開いたままになります。

そこで次のレッスンでは、同じメニューをJavaScriptで動かします。しくみはほとんど同じなので、ここまでが理解できていれば大丈夫です。

まとめ

  • メニューは position: fixed と right: -100% で画面の外に隠しておく
  • :checked ~ .global-nav で right: 0 にすると、画面の中へスライドして出てくる
  • ボタンは z-index でメニューより手前に出す
  • + はすぐ後ろの兄弟だけ、~ は後ろの兄弟すべて
最近の記事 おすすめ記事

記事一覧を表示するには、カスタム投稿「演出効果」にて、4つ以上記事を作成してください。

記事一覧を表示するには、カスタム投稿「演出効果」にて、4つ以上記事を作成してください。

演出効果
  • カテゴリーなし
TOP