LoginSignup
126

More than 3 years have passed since last update.

CSSだけで簡単にドロワーメニュー(ハンバーガーメニュー)を作る

Last updated at Posted at 2019-08-14

ハンバーガーアイコンの☓になる動き、横からメニューが出てくる動き、メニューが出てるときはメインエリアを暗くすることまで、すべてCSSのみで実装可能。

See the Pen drawer menu by himeka223 (@himeka223) on CodePen.

解説

CSSのみで作るドロワーメニューの動きは、inputタグのcheckboxで制御している。

  • チェックがされた場合… メニュー横から出現、アイコンを☓に、メインエリアを暗く。
  • チェックがはずれた場合… すべてもとに戻る。

checkboxlabel の連動

checkboxlabel と連動させ、
labelのクリックで、checkboxにチェックが入るように。

hrader.html
<!-- checkbox自体は非表示 -->
<input class="l-drawer__checkbox" id="drawerCheckbox" type="checkbox" >
<!-- ハンバーガーアイコン -->
<label class="l-drawer__icon" for="drawerCheckbox">
  <span class="l-drawer__icon-parts"></span>
</label>
<!-- 背景を暗く -->
<label class="l-drawer__overlay" for="drawerCheckbox"></label>

アイコンとの連動

inputタグのid="drawerCheckbox"と、labelタグのfor="drawerCheckbox"同じ値を設定することで、inputlabelを紐付け、連動をさせている。

暗くなる背景との連動

1つのinputcheckboxに複数labelを連動できるので、背景を暗くするエリアをlabelとし、for="drawerCheckbox"で、連動させ、ここをクリックしてもチェックが外れるようにしている。

checkboxの非表示

labelに連動させることで、checkboxの表示は不要なので、display: noneで非表示にしておく。

ハンバーガーアイコン

アイコンもCSSで実装している。

header.html
<!-- ハンバーガーアイコン -->
<label class="l-drawer__icon" for="drawerCheckbox">
  <span class="l-drawer__icon-parts"></span>
</label>
l-drawer.scss

// ハンバーガーアイコン
&__icon{
  cursor: pointer;
  display: block;
  width: 56px;
  height: 60px;
  position: fixed;
  right: 0;
  // ハンバーガーアイコンの中の線
  &-parts,
  &-parts:before,
  &-parts:after{
    background-color: #000;   
    display: block;
    width: 26px;
    height: 2px;
    position: absolute;
    top: 0;
    right: 0;
    left: 0;
    bottom: 0;
    margin: auto;
  }
  &-parts:before,
  &-parts:after{
    content: " ";
  }
  &-parts:before{
    top: 16px
  }
  &-parts:after{
    top: -16px
  }
}

label

ハンバーガーアイコンの外枠

  • アイコンの大きさを決めブロック要素にする。
  • position: fixedで、位置を、ブラウザ自体に固定する。(今回は右上に固定するため、right: 0指定)
  • cursor: pointer;ホバー時のカーソルを矢印でなく、指マークにする。

spanlabelの子要素)

ハンバーガーアイコンの三本線部分。
span自体で、真ん中の線を作り、spanafterbeforeの疑似要素で、で上の線と下の線を作っている。

  • 線1本の長さ・太さをwidthheightで決める。色はbackground-colorで指定。
  • position: absolute;margin: autolabelの中の上下中央揃えにする。
  • 上下の線:after:before疑似要素なので、content: " "を指定。
  • 上下の線の位置を、上はtop: -16pxと下はtop: -16pxというように、移動させることで、三本線に。

オーバーレイ

メニューが開いてるときは、メインエリアを暗くする。

l-drawer.scss
// ドロワーメニュー開いた時のメインエリアを暗く
&__overlay{
  background: #000;
  opacity: 0;
  // display: none; //opacity: 0;で非表示はできているため、display: none;は削除
  pointer-events: none; //ポインタの動作全部無効化
  width: 100%;
  height: 100%;
  position: fixed;
  top: 0;
  right: 0;
}

* メニューが開かれる前は非表示にするため**opacty: 0display: none;を設定する
* width: 100%;height: 100%;を指定し、メインエリア全体にかかるように。
* position: fixed;でブラウザに固定表示。

:writing_hand_tone1: 08/22 コメントにて下記ご指摘を頂きました。ありがとうございます。

  • pointer-events: none;でポインタの動作を無効化する。
  • opacity: 0;で非表示はできているため、display: none;の記載はいらない。

メニュー

l-drawer.scss
// ドロワーメニュー
&__menu{
  background: #ffffff;
  color: #000;
  max-width: 100%;
  width: 320px;
  height: 100vh;
  overflow-y: auto; //スクロール
  -webkit-overflow-scrolling: touch; //スクロール(SP)
  position: fixed;
  top: 0;
  right: -320px;
}
  • メニューが見えづらいので背景色を指定。
  • widthでメニューの幅、heightでメニューの高さの指定。100vhとすることでブラウザの高さ分の値が取れる。
  • overflow-y: auto;-webkit-overflow-scrolling: touch;を指定して、メニュー内のみスクロールできるようにする。
  • position: fixed;でブラウザ自体に固定。
  • right: -320pxでメニュー幅分、右端からさらにに移動させることで、クリック前はメニューを隠す。

:checked ~で、クリック後のスタイルを指定

checkboxに対して、:checkedをつけると、チェックボックスにチェックが入ってる時だけの指定が出来る。
~セレクタは、同じ階層で、後に出てくる要素すべてを指定する。

この2つを組み合わせ、:checked ~と指定すると、チェックボックスにチェックが入ってる時、同階層であとに出てくる要素への指定ができる。

今回は、上で説明した、ハンバーガーアイコン、オーバーレイ、メニューのクリック後のスタイルを設定する必要がある。

クリック後のハンバーガーアイコン

l-drawer.scss
// ハンバーガーアイコン
.l-drawer__icon{
  .l-drawer__icon-parts{
    background: transparent;
  }
  .l-drawer__icon-parts:before{
    -webkit-transform: rotate(-45deg);
    transform: rotate(-45deg);
    top: 0;
  }
  .l-drawer__icon-parts:after{
    -webkit-transform: rotate(45deg);
    transform: rotate(45deg);
    top: 0;
  }
}
  • 真ん中の線は、background: transparent;で背景を透過させ見えなくする。
  • 上下の線は、top: 0;で位置を戻し、transform: rotate(-45deg);で、それぞれ45°回転させる。

クリック後のオーバーレイ

l-drawer.scss
// メインエリアを暗くする
.l-drawer__overlay {    
  opacity: 0.3;
  pointer-events: auto; //ポインタの動作デフォルトに戻す
}

* display: block;opacity: 0.3;で表示させる

:writing_hand_tone1: 08/22 コメントにて下記ご指摘を頂きました。ありがとうございます。

  • pointer-events: none;でポインタの動作を無効化してたのをautoにしてデフォルトに戻す。
  • opacity: 0.3;で表示はできているため、display: block;の記載はいらない。

クリック後のメニュー

l-drawer.scss
// メニューをだす
.l-drawer__menu {
  right: 0;
}
  • 左にマイナスで隠してため、right: 0に指定して、位置を右端に揃える

z-indexで重なりを調整

l-drawer.scss
// z-indexの指定(1がメインエリア)
&__icon{
  z-index: 4;
}
&__menu{
  z-index: 3;
}
&__overlay{
  z-index: 2;
}
  • メインエリアガ一番下として、オーバーレイメニューハンバーガーアイコンとなるように調整
  • まとめて書くことで調整しやすくする。

transitionで動きをスムーズに

l-drawer.scss
// 動きをスムーズに
&__icon-parts,
&__icon-parts:after,
&__icon-parts:before,
&__overlay,
&__menu{
  -webkit-transition: all .7s ;
  transition: all .7s ;
}
  • 同じスピードでと動くようにまとめて記載。
  • allですべての変化するプロパティに、.7sで0.7秒かけて変化する指定。

まとめ

inputのcheckboxやradioを使えばjsを使わなくてもCSSでできることが増えそう。
同じような考えでモーダルも実装可能である。

参考サイト

ドロワーやモーダルをCSSだけで実現する方法 | HPcode
CSSだけで簡単!ハンバーガーメニューの作り方(スマホ対応)

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
126