ハンバーガーボタン 何で作ってる?僕なりの作り方を解説してみる。
もう年末ですね。
去年の今頃は風邪で鼻水だらだらの記憶がありますが、皆さんは如何お過ごしですか?
どうも、しばおです。
さて、いきなりですが、皆さん ハンバーガーボタン ってどうやって作ってます?
ハンバーガーボタン の作り方をググったりすると、空っぽの span
タグ 3個で作ってたり、div
タグ や チェックボックスで作ってたりするのをよく見かけます。
でもね。僕的には、button
要素がベストだと思っているんです。
そこで今回は、なぜハンバーガーボタンを button
要素で作った方がいいのかや、僕なりの作り方をできる限り詳しく解説をしてみたいと思います。
ちなみにこの記事は、ある程度、HTMLやCSS、JavaScriptを使った基本的なコーディングを理解している人向けになりますので、CSSって何?って方は先に、基本的なコーディングを学習しておいて下さい。
ハンバーガーボタン ってなに?
そもそもハンバーガーボタンって何?って話なのですが、最近のスマホサイトでは当たり前になってきた、三本線のボタンのことです。
つまり、下記の様なボタンです。
See the Pen Hamburger use jQuery by Shiba Hiro (@hilosiva) on CodePen.36915
ちなみにこれが今回解説する完成品のコードです。
「解説なんていらないから、ハンバーガーボタンを作るコードだけ欲しい!」って方はこのコードを見てもらえば完結ですね。
お疲れさまでした。
はい。ということで、これがハンバーガーボタンです。
真ん中の線がお肉、上下の線がバンズに見えることから、そう名付けられたとか・・・?
なんせ、このボタンをクリックすると、ドロワーメニューと言って、サイトのメニューがスパーンって横から表示されるのが一般的ですよね。
昔は、糞UIと騒がれてましたが、今となってはメニューを開くボタンとして一般的に認知されています。
じゃあ、まず、このハンバーガーボタンを実装するための HTML を考えていきましょう。
僕流の ハンバーガーボタン のHTML
結論から言うと、僕は以下のような HTML でマークアップしています。
まぁ、id名やclass名などはお好きに変えて下さい。
今回僕は、とりあえず深く考えずに、FLOCSSというCSS設計案的に書いたので、「c-」や「p-」って何?って方はFLOCSSというCSS設計案を確認して頂ければと思います。
なぜ button
要素なのか?
span
要素だけや、チェックボックスじゃだめなの?
よく、ハンバーガーボタンに関してググると、span
タグ3つ並べて作ったり、div
タグだけで作ってたりするのを見かけますよね。
あ、あと、チェックボックスを使って CSS だけでドロワーメニューを実装するパターンもありますね。
が、結論僕は、 button
要素がいいと思ってるんです。
理由はいくつかあるのですが、まずそもそも、span
要素や div
要素って、フォーカスが当たらないんです。
どういう事かって言うと、Webサイトをキーボードだけで操作する時は、Tab キーを使って、リンクや、フォームの入力項目にフォーカスを当てて、Enter キーでリンク先に移動したり、フォームに入力したりするんです。
このフォーカス が当たる要素というのは、基本的には、a
要素 と フォームのコントロール部品の 要素だけです。
つまり、span
要素や div
要素で作ったハンバーガーボタンには、フォーカスが当たらないので、キーボードだけで操作している人は、ハンバーガーボタン を押すことができないのです。
以下は、button
要素を使わずに、div
要素と、span
要素だけで、ハンバーガーボタン を作ってみました。
See the Pen Hamburger use span by Shiba Hiro (@hilosiva) on CodePen.36915
この「Result」パネルのプレビュー画面を1度クリックしてから、tab キーを押してみて下さい。
ほら、フォーカスが当たらないでしょ?
つまり、キーボードだけでは ハンバーガーボタン をクリック出来ないのです。
って思ったかもしれませんが、その場合はきっと、ハンバーガーボタン にする際、input
要素を display: none
にして、label
要素 で実装しませんか?
ってなるとですよ。
label
要素にはそもそもフォーカスが当たらないので、 input
要素 を display: none
したら、結局、フォーカスが当たる要素がないんですよ。
以下のサンプルは、input
要素で、チェックボックスを作って、label
要素でハンバーガーボタンを実装してみました。
See the Pen Hamburger use input by Shiba Hiro (@hilosiva) on CodePen.36915
また、この「Result」パネルのプレビュー画面を一度クリックしてから、tab キーを押してみて下さい。
ほら、これもフォーカスが当たらないでしょ?
label
要素にはそもそも、フォーカスが当たらないので、input
要素 を display: none
しちゃうと、結局フォーカスが当たる要素がないんです。
なるほど。
確かに、フォーカスは当てれます。
でも、label
要素にフォーカスがあたっても、キーボードのみの操作で、そのラベルと関連する チェックボックスのチェックをオンにすることができないのです。
以下は、さっきのサンプルに、tabindex
属性でlabel
要素にフォーカスが当たるようにしてみました。
See the Pen Hamburger use input tab-index by Shiba Hiro (@hilosiva) on CodePen.36915
どうですか?
フォーカスは当たるけど、Space キーを押そうが、Enter キーを押そうが、選択ができないですよね?
つまり、span
要素 や div
要素、チェックボックスでハンバーガーボタンを作ったとしても、見た目は問題ないが、キーボードのみで操作している人は、メニューを展開することができないのです。
確かに、マウスを使えばいいかもしれません。
ですが、身体的理由でマウスの操作ができない方もいるかも知れませんし、もしあなたがデスクトップパソコンを使ってたとして、急にマウスが壊れたらどうです?
ほら、キーボードのみで操作しなければいけないでしょ?
こんな時に、アクセシビリティが低いサイトだと、メニューが展開できず、「他のページに移動できない!」なんてことになるのです。
ということで、ハンバーガーボタンは button
要素が良いと思っています。
aria-controls
属性とか、aria-expanded
属性って何?
よく見かけるハンバーガーボタンの解説コードでは、こんな属性付いてなかったりしますが、これは一体なんなのかって話です。
これも、アクセシビリティを向上させるための属性です。
aria-controls
属性- この属性が指定されている要素が、コントロールする対象となる要素を指定する属性。対象の要素にid属性で固有名を決めて、そのID名で指定する
aria-expanded
属性-
この要素が操作する対象の要素が、現在展開されているか、展開されていないかという状態を表す属性。属性値に
true
を指定すると展開中を表し、false
を指定すると現在展開していないことを表す
という属性たちです。
つまり、このaria-controls
属性を使えば、このボタンがどの要素を操作するボタンなのかを視覚的に見てるユーザー以外にも伝えることが出来ます。
そして、aria-expanded
属性は、ドロワーメニューが表示されるタイミングで true
にしたり、非表示になるタイミングで false
にすることで、視覚的に見てるユーザー以外にも、今メニューがどういう状態になっているかを伝える事ができます。
これらの属性のおかげで、Webサイトを視覚的に見ているユーザー以外でも、ちゃんとメニューの表示状態を把握することができるのです。
じゃあさ、「メニューを開閉する」ってテキストいるの?
多くのハンバーガーボタンのサンプルコードをみると、確かにこんなテキスト書いてないですよね。
でも、この様なテキストがないと、音声ソフトなどのスクリーンリーダーを使ってWebサイトを見ているユーザーに、これがメニューを表示するためのボタンであることが伝えられません。
これは、別に、aria-label
属性という属性を使って、指定する方法でもいいと思います。
いずれにしても、この様なテキストや、aria-label
属性を使うことで、音声ソフトなどのスクリーンリーダーでWebサイトの内容を理解しているユーザーにも、このボタンを押せば何が起こるのかが、明確にわかるようになります。
でも、このテキストって、視覚的にはいらないですよね?
という事で、CSSでそのテキストを非表示にしちゃいます。
ちなみに、こんな感じでテキストを非表示にする場合は、aria-label
属性を使うより、直接HTMLにテキストを配置した方が良いんじゃないかなと思います。
aria-label
属性はあくまで支援ソフト向けの属性であって、視覚的なユーザー向けのものではないため、もし何らかの影響(ネットワークの不調など)で、CSSがうまく読み込まれなかったとしたら、何のテキストも書いてない空っぽのボタンとなり、視覚的に見ているユーザーにはどんな役割のボタンなのかが伝わらないからです。
ということで、この記事ではHTMLに直接「メニューを開閉する」というテキストを配置して、CSSでそのテキストを非表示にします。
あ、ちょっとまって!display: none
はやめてね。
なぜなら、display: none
を使うと、音声読み上げソフトも読み上げないです!
ってことで、それ以外の方法で非表示にします。
具体的にどんなコードで非表示してるかは、後で言うとして、いずれにしても、僕はこんな感じで、ハンバーガーボタンのHTMLを書いています。
See the Pen Make Hamburger Button Step 0 by Shiba Hiro (@hilosiva) on CodePen.36915
ちなみに、button
要素に、type
属性 で button
を指定することは忘れないでくださいね。
button
要素の デフォルトの type
属性は、submit
なので・・・。
僕流の ハンバーガーボタンの CSS
じゃあCSSはどうしてるのかっていうところも、簡単に説明しておきたいと思います。
まずは、さっきのテキストを非表示する方法から紹介しましょうか。
スクリーンリーダー用のテキストを非表示にするスタイル
結論から言うと、以下のスタイルを使って非表示にしています。
って感じですかね。
position: absolute
で 飛ばして、ボックスを 1px
にしたり、clip
で切り取ったりして、ボックスを越えたものを overflow: hidden
で隠す!
という、わりと無理矢理テキストを隠すという呪文です。
でも、この方法だと、display: none
などとは違い、ちゃんと音声ソフトでも読み上げられます。
ということで、この u-visuallyHidden というclassを「メニューを開閉する」というテキストを包んでる span 要素に指定してます。
See the Pen Make Hamburger Button Step 1 by Shiba Hiro (@hilosiva) on CodePen.36915
これで、無事テキストが非表示になりました。
button
要素 のスタイルはどんな感じ?
そしたら、実際にハンバーガーボタンに関するスタイルを見ていきましょう。
まずは、button
要素のスタイルですね。
button
要素には、「c-button
」というclassと、「p-hamburger
」というclassの2つのクラスを当ててます。
まぁ、ここはFLOCSS的に書いたのでこんな感じですが、別に変えもらって問題ありません。
いずれにしても、button
要素には以下のようなスタイルを当てています。
c-button
には、どのボタンにも使いそうな、汎用的なボタンのスタイルを当てて、p-hamburger
には、このハンバーガーボタンの枠のスタイルを当てています。
まぁ、ハンバーガーでいうと、ハンバーガーを包んでる紙の部分のスタイルって事ですね。
特別なことはとくに何もしてないのですが、ボタンの位置やら、サイズやら、角丸やら、色はお好きに変更して下さい。
button
要素の注意点
まぁ、ちょっと注意しておいてほしいポイントがひとつあるので、そこの説明だけしておきますね。
それが、フォーカス時のスタイルですかね。
今回僕は、p-hamburger
に outline: none
を指定してます。
これめちゃめちゃよく見かけるんですが、これ個人的には結構危険だと思ってます。
確かに付けたくなる意味はわかります。
だって、デフォルトのフォーカス時に表示される、あの青いアウトラインって、デザインとマッチしないなどの理由で、使いたくなかったりするんですよね。
でも、あのアウトラインが無くなると、キーボードだけで操作してるユーザーは大変です。
なんでかって言うと、ハンバーガーボタンにフォーカスが当たっているかどうかが視覚的にわからなくなっちゃうんですよね。
以下は、単純に outline: none
を使った、ハンバーガーボタンです。
See the Pen Hamburger use outline-none by Shiba Hiro (@hilosiva) on CodePen.36915
Tab キーを使って、ハンバーガーボタンにフォーカスを当てて、Enter キー で選択してくみて下さい。
どうですか?ちゃんと選択できるけど、フォーカスが当たっているかわからないでしょ?
これが、個人的に危険だなぁ。って思ってることです。
ま、めちゃめちゃ見かけますけどね。
だからら、基本的に、outline: none
は使わないようにしましょう!
でも、あの青いアウトラインが嫌!ってのもわかります。
そこで、僕がよく使うのテクニックが、フォーカス時には、box-shadow
を使ってフォーカスが当たっていることがわかるようなスタイルを当てています。
あと、これに、ちょっとアニメーションを加えることで、オシャンティーにしています。
これで、ハンバーガーを包む紙、つまりボタンの枠の部分ができました。
See the Pen Hamburger use outline-none by Shiba Hiro (@hilosiva) on CodePen.36915
p-hamburger__line
はどんなスタイル?
次は、その中の「 p-hamburger__line
」というclassです。
この、「p-hamburger__line
」というclassで、ハンバーガーのお肉とバンズを作っています。
まぁ、なのでこの子がハンバーガーですね。
お肉の作り方
お肉を作るには、まず、p-hamburger__line
に、お肉の幅と高さを設定し、背景色をつけることで、お肉が完成します。
そして、そのお肉を、先程作ったp-hamburger
のど真ん中に持っていきます。
具体的には以下の様なCSSになります。
まぁ、これもそんなに変わったことはしてませんが、width
と、height
を使って お肉のボックスを作ってます。
でそれを、position: absolute
を使って、親要素となる button
要素のド真ん中に持ってきてます。
left
、right
、top
、bottom
が全て、0
だから、親要素の領域を把握できてるし、幅と高さもちゃんと指定しているので、margin: auto
が効きます。
つまり、ど真ん中に来ます。
See the Pen Make Hamburger Button Step 3 by Shiba Hiro (@hilosiva) on CodePen.36915
ここまで書けば、この時点でこんな感じになると思います。
バンズの作り方
バンズは、::before
と ::after
で作っています。
まず、::before
と::after
に、position: absolute
を指定して、親要素である、お肉と、同じ位置に同じ大きさになるようにスタイルを指定します。
で、::before
のtop
をマイナスで指定して上に配置し、::after
の方には、プラスの値を指定することでお肉の下にバンズの位置を調整しています。
これによって、span
要素ひとつで、ハンバーガーを作っています。
See the Pen Make Hamburger Button Step 4 by Shiba Hiro (@hilosiva) on CodePen.36915
JavaScript はどうしてるの?
もちろん、JavaScript に関してもいろんな方法があると思いますが、個人的なポイントは、2つです。
- メニューが表示中の時に、
html
要素 にclass を付加する aria-expanded
属性のtrue / false
を切り替える
まぁ、ドロワーメニューを作るだけなら、これが出来れば問題ないのかなぁと思っています。
なので、ネイティブなJavaScriptだと以下のようなコードでそれが実装できます。
これで、上に挙げたポイントがクリアできるわけです。
メニューが表示中の時に、html
要素 にclass を付加する
さて、これはなぜやってるかって話も入れておきますね。
まぁ、ぼくはドロワーメニューもそうですが、この様な何かをクリックして、要素が表示されるようなものを作る時は、だいたい、html
要素に、classをつけるようにしています。
なぜかっていうと、単純に、html
要素って全ての要素を包んでる、母なる要素なので、ここにクリックされた時だけ classを付けちゃえば、子孫セレクタを組み合わせたりすれば、html
要素内のどの要素にでも スタイルを指定できるからです。
なので、ドロワーメニューの場合は、ハンバーガーボタンをクリックした時に、html
要素 に 「is-drawerActive
」的なclass を付けたら、 以下のようなスタイルで、ドロワーメニューを操作できます。
ちなみに、このclassを活用したら、ハンバーガーボタンも、メニュー表示用のスタイルに切り替えることができますね。
aria-expanded
属性の true / false
を切り替える
そして、2つめのポイントが、aria-expanded
属性を切り替えるって処理ですね。
まぁ、HTMLのマークアップの時にも書きましたが、この属性は、操作対象となる要素が、現在表示されているのか、非表示なのかをスクリーンリーダーなどに知らせることができる属性です。
一般的に ハンバーガーボタンをクリックしたら、ドロワーメニューが、横からとかピューンと登場するかと思います。
なので、基本的にはハンバーガーボタンが操作する対象は、そのドロワーメニューというわけです。
で、そのドロワーメニューって、サイトを表示した時点では、非表示になっていることが多いと思います。
つまり、そのような非表示時の時は、aria-expanded
属性が false
である必要があります。
で、ハンバーガーボタンをクリックして、ドロワーメニューが表示されたら、その時は、この、aria-expanded
属性を true
にする必要があります。
これを JavaScript を使って切り替えているのです。
これで、スクリーンリーダーなどを使っているユーザーに、メニューが表示されたことを知らせるサポートができます。
See the Pen Make Hamburger Button Step 5 by Shiba Hiro (@hilosiva) on CodePen.36915
ドロワーメニュー展開中のハンバーガーボタンのスタイル
じゃあ、最後にハンバーガーボタンをクリックして、ドロワーメニューが表示されている時の、ハンバーガーボタンのスタイルについて解説したいと思います。
結論からいうと、以下の様なスタイルを僕はよく書きます。
こんな感じです。
さっき JavaScriptで、body要素に「 is-drawerActive
」というclassをつけるって言っていいました。
なのでそれを活用しても良かったんですが、今回は、属性セレクタも活用しちゃいました。
つまり、aria-expanded
属性が true
の時という属性セレクタでスタイルを当てています。
まぁ、やっていることは、シンプルで、真ん中のお肉の背景色を透明にして、バンズは真ん中に戻して、45度回転させて、「☓」にしています。
アニメーションの感じとかは、自由に変えちゃってくださいね。
これで、ハンバーガーボタンの完成です。
See the Pen Hamburger use jQuery by Shiba Hiro (@hilosiva) on CodePen.36915
まとめ
如何だったでしょうか?
Shibajuku の授業でも、僕なりのハンバーガーボタンの作り方をこんな感じでガッツリ作り込む授業してるんですが、今回はそれを記事にして解説してみました。
まぁ、僕のこだわりポイントとしては、アクセシビリティを意識したハンバーガーボタンを作るってことですかね。
もっとアクセシビリティにこだわることもできる気もしますが・・・w
なにわともあれ、このハンバーガーボタンの作り方がみなさんの参考になれば幸いです。
ちなみに、Shibajukuでは、こういうアクセシビリティを意識したコーディングを結構授業でやってるので、興味がある方は一度覗いてみてください。
では。
おまけ
CDNで読み込むタイプのやつですが、vue.js 版も作ってみました。
See the Pen Hamburger use Vue.js by Shiba Hiro (@hilosiva) on CodePen.36915