こんにちは。 webデザイン学習中、mamenoです。
前回、ハンバーガーメニューの作り方(疑似要素で頑張ろう編)という記事で、ハンバーガーメニューが開いた時の背景を疑似要素で作るパターンについて書きました。 mameno-web.hatenablog.com
今回は疑似要素を使うのではなく、JavaScriptで背景用の空タグを生成する方法で書いていきたいと思います。
- 今回のゴール
- 1. ハンバーガーメニューを作る(HTML編)
- 2. ハンバーガーメニューを作る(CSS編)
- 3.ハンバーガーメニューの挙動を作る(JS編-1)
- 4.JavaScriptで背景を生成して制御する(JS編-2)
- 終わりに
※1~3(JS編-1)までは前回とほぼ同じです。
メニュー展開時の背景のマスクについてについてだけ変更しています。
今回のゴール
動きとしては、 1. 三本線(ハンバーガーメニュー)をクリック(タップ) 2. 上からメニューが出てきて、背景が暗くなり、ハンバーガーは×ボタンになる 3. ×ボタン or 暗い背景をクリック(タップ)するとメニューが閉じる となります。
See the Pen Untitled by mameno (@mameno_design) on CodePen.
この時の暗い背景を、三本線(ハンバーガーメニュー)をクリックしたときにJavaScriptでspan
タグを生成して作っちゃおうというお話です。
1. ハンバーガーメニューを作る(HTML編)
まずは、HTMLを記述します。
See the Pen Untitled by mameno (@mameno_design) on CodePen.
今回、ハンバーガメニューを作るにあたって大切にしたことは、2つ。
- そもそものHTMLに空の要素は作らない
- スマホバージョンとPCバージョンのメニューは分けない
順に説明していきます。
空の要素を作らない
三本線アイコンについて
ハンバーガーメニューのアイコンというと、HTML上にspan
タグを3つ並べて作るパターンをよく見かけます。
が、できればhtml上には不要な要素は置いておきたくない。
ということで、今回はbutton
タグの中にspan
タグを一つ入れそこに一本線を作り、
:before
、:after
で残り2本を作るという方法にしました。
<button type="button" class="c-button p-hamburger js-hamburger" aria-controls="global-nav" aria-expanded="false">
<span class="p-hamburger__line">
<span class="u-screenReaderText">メニューを開閉する</span> //ここはスクリーンリーダー用で画面上には表示されない
</span>
</button>
メニュー展開時の背景のマスクについて
ハンバーガーメニューが開いた時の背景のマスクについては、ハンバーガーメニューが押されたらJS側でspan
タグを入れるようにするので、厳密に空要素が全くないとは言えませんが、初めからあるということは避けるようにしました。
スマホバージョンとPCバージョンのメニューは分けない
メニューを分けると、HTML上にスマホバージョンと
PCバージョンのメニューが2つ存在することになるわけです。
見た目上は出し分けているので問題ないかもしれませんが、こちらも音声読みあげソフトを使用した時には、
2回メニューが読まれるわけなので鬱陶しいかなということで、HTMLは最小限の記述でcssでなんとかしていくという方法にしました。
(今回は非常にシンプルなメニューだったということもあり)
音声読み上げ用クラスについて
ちなみに、.u-screenReaderText
クラスがついているspan
は、
音声読み上げソフトを使用した際に「ここを押すとナビゲーションメニューが開閉できますよ〜」と教えるためのもので、
画面上には必要ないので、後述するcssで見えなくしておきます。
2. ハンバーガーメニューを作る(CSS編)
次はCSSです。
.u-screenReaderText
用に隠す記述- ナビゲーションのスタイル
- ハンバーガーボタンのスタイル
を順番に記述します。 (767px以下でハンバーガーメニューに変わります。まだ動きません。)
See the Pen Untitled by mameno (@mameno_design) on CodePen.
ハンバーガーメニューのcssについては、いろいろな方が書かれているのでここでは割愛します。
3.ハンバーガーメニューの挙動を作る(JS編-1)
- CSSに、
.is-active-drawer
がついた時の要素について追記(CodePen CSSの下にまとめてあります) - JSにて、ハンバーガーボタンに
.is-active-drawer
をつける(外す)処理と、aria-expanded
のtrue/falseを入れ替える処理の記述(この時点ではハンバーガーボタンのみでメニューの開閉)
See the Pen Untitled by mameno (@mameno_design) on CodePen.
aria-expanded
って?
要素、またはそれが制御する別のグループ化要素が現在展開されているか折りたたまれているかを示します。
W3Cリファレンス より
なくても見た目には影響しませんが、アクセシビリティ的な観点から記述した方がいいものです。多分。
クラスの付け替えだけだと、aria-expanded
がfalseなのに見た目では展開している感じになってしまうのできちんと書き換える処理を加えています。
4.JavaScriptで背景を生成して制御する(JS編-2)
- CSSに、is-active-maskがついた
span
要素について記述(先ほどのさらに下に追記) - JavaScriptに、ハンバーガーボタンを押したときの背景の動きについて記述
ハンバーガーボタンを押した時の処理の中に、以下を追記します。
//マスク用spanタグの生成
const newEl = document.createElement("span");
newEl.classList.add("is-active-mask");
if (document.querySelector(".is-active-mask") === null) {
//is-active-maskが存在しなければ処理をする
globalNav.appendChild(newEl).addEventListener("click", () => {
body.classList.remove("is-active-drawer");
hamburgerButton.setAttribute("aria-expanded", false);
});
}
動きとしては、
ハンバーガーメニューがクリック(タップ)される→
is-active-mask
というクラスがついたspan
タグを生成する→
is-active-mask
というクラスがあるかどうかをif
文で判別し、存在しなければglobalNav(.js-globalNavクラスがついた要素)
の一番最後の子要素に追加する→
そしてその要素にそのままクリックイベントを定義する
という流れになります。
以下はそのデモになります。
See the Pen Untitled by mameno (@mameno_design) on CodePen.
終わりに
いかがでしたでしょうか。
今回は、JSで要素を生成してクリックイベントを定義する方法で作ってみました。
このコードのポイントは、作った要素があるかどうかを判別するのを忘れないことでしょうか。
これをしないと、「そんな要素ないよ!!」って怒られます。
ということで、これが何かの参考になれば嬉しいです。
ご覧いただき、ありがとうございましたー