ドロワーメニュー

ページの隅っこにあるやのアイコンをタップするとメニューがスライドしてくるの、よく見かけますね。引き出しみたいに出し入れできるメニューだからドロワーメニューとかって言います。ここではそんなドロワーメニューをCSSで作ってみます。
開閉する仕組み
メニューが開閉する仕組みは、これまでのサンプル同様<input>
と<label>
を使った方法で、今回はラジオボタンじゃなくて、チェックボックスを使います:)。
ページ全体のHTMLの構造は以下の通り。
<body>
<input type="checkbox" id="drawer">
<label for="drawer" class="open"></label>
<label for="drawer" class="close"></label>
<nav class="menu">
⋮
</nav>
<div class="contents">
<header>
⋮
</header>
<article>
⋮
</article>
<footer>
⋮
</footer>
</div>
</body>
メニューを開閉するためのボタンとなるlabel要素は2つ用意しておき、ひとつは開く・閉じるの両用、もうひとつを閉じる用としておきます。
両用の<label for="drawer" class="open">
は、常に見えているボタンの形をしたもの。閉じる用の<label for="drawer" class="close">
は、全面を覆うように固定配置しておきます。
そして、スイッチの役割となるチェックボックスは、ページの先頭に設置。

これが:checked
になった時に、それ以降の兄弟要素<label>
と<nav>
のスタイルを変える仕組みです。

全面を覆っている閉じるボタンは、メニューが閉じている時はpointer-events: none
でポインターでの操作を無効にしておき、メニューが開いた時にはauto
にして、クリックできるようにします。スライドショーの矢印ボタンの時と同じ方法ですね;)。
.close {
z-index: 1;
inset: 0;
pointer-events: none;
transition: background-color .6s;
}
#drawer:checked ~ .close {
pointer-events: auto;
background-color: rgba(0,0,0,.3);
}
pointer-events: none
でポインターイベントが無効になるので、前面を覆っていても、その下のコンテンツには触ることができるってわけ:D。
ドロワーメニューが開いたらスクロールをロックする
ドロワーメニューが開いている時には、下のコンテンツのスクロールを止めたいって時もあるでしょう。そんな時には、以下のように、ページ全体をひとつのdiv要素で括って、その要素内でスクロールするようにします。
<body>
<div class="container">
<input type="checkbox" id="drawer">
<label for="drawer" class="open"></label>
<label for="drawer" class="close"></label>
<nav class="menu">
⋮
</nav>
<div class="contents">
⋮
</div>
</div>
</body>
body要素の内側のdiv要素.container
に、以下のようにスタイルを指定すれば、html要素ではスクロールしなくなり、.container
内でスクロールするようになります。
.container {
position: absolute;
inset: 0;
overflow: auto;
}
そうすると、ドロワーメニューが開いた時に、閉じるボタン用のlabel要素がページ全体を覆っている故、下のコンテンツに触れなくなって、スクロールもできなくなります:o。

ウィンドウの幅に合わせてメニューを使い分ける
ドロワーメニューは、画面が狭い時だけ使えればよくて、画面が広い時にはコンテンツ内にメニューを表示させときたいって時もあるでしょう。
そんな時はMedia Queriesという構文を使います。メディアクエリとは、メディアの特性に合わせてスタイルを出し分けるための方法。詳しくは後述。
例えば、以下のように指定すれば、画面の横幅が520px以上の時にはドロワーメニューのアイコンが非表示になり、画面の横幅が519px以下の時にはコンテンツ内のメニューが非表示になります。
@media (min-width: 520px) {
.open {
display: none;
}
}
@media (max-width: 519px) {
header nav {
display: none;
}
}
上のサンプルでは、メディアクエリを使って、ブラウザの横幅に合わせて、普通なメニューを表示するスタイルと、ドロワーメニューを表示するスタイルを出し分けてるということになります。
ブラウザの横幅を狭くしていくと、コンテンツ内のメニューが消えて、ドロワーメニューのアイコンが現れます。
パッと切り替わるより、もうちょっと自然な感じに切り替わるようにしてみたいですね。CSSの指定を以下のように変えてみます。
.open {
transform: translate(0, -100%);
}
#drawer:checked + .open {
transform: translate(250px, 0);
}
@media (max-width: 480px) {
.open {
transform: translate(0, 0);
}
}
display: none
で急に消すんじゃなくて、要素の透明度や位置を調整して隠すようにしてみました。それぞれtransitionプロパティを指定してゆっくり隠れるようにしています。

パララックス