Edited at

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

ハンバーガーアイコンの☓になる動き、横からメニューが出てくる動き、メニューが出てるときはメインエリアを暗くすることまで、すべて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だけで簡単!ハンバーガーメニューの作り方(スマホ対応)