ハンバーガーメニューを作る
市民権を得たのかこの先淘汰されるのか、3本線で表現されるメニューボタンのハンバーガーメニューを作成します。
さまざまな作り方があるようですが、ここでは button 要素と疑似要素を使って作成します。
完成したハンバーガーメニュー
ここで作成するハンバーガーメニューは、 HTML ・ CSS ・ JavaScript を使っています。次のコードで、ボタン部分のアニメーションやメニューの表示・非表示が行えるようになります。 nav 要素の部分がドロワーメニューになるのですが、この部分の表示非表示は含んでいません。
まずは、HTML。
<body>
<button type="button" id="hamburger-btn" class="c-hamburger" role="button" aria-expanded="false" aria-controls="drawer">
<span class="c-hamburger__line">
</span>
</button>
<nav id="drawer" aria-labelledby="hamburger-btn">
</nav>
</body>
スタイルシート。
.c-hamburger {
position:relative;
width: 38px;
height: 38px;
border: none;
outline: none;
background: transparent;
outline: none;
-webkit-transition: all .3s ease-in-out;
transition: all .3s ease-in-out;
}
.c-hamburger__line {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
display: block;
margin: auto;
width: 18px;
height: 2px;
background-color: #011729;
-webkit-transition: inherit;
transition: inherit;
}
.c-hamburger__line::before,
.c-hamburger__line::after {
content: '';
position: absolute;
display: block;
width: 100%;
height: 100%;
background-color: inherit;
-webkit-transition: inherit;
transition: inherit;
}
.c-hamburger__line::before {
top: -5px;
}
.c-hamburger__line::after {
top: 5px;
}
.c-hamburger[aria-expanded="true"] .c-hamburger__line {
background-color: transparent;
}
.c-hamburger[aria-expanded="true"] .c-hamburger__line::before,
.c-hamburger[aria-expanded="true"] .c-hamburger__line::after {
top: 0;
background-color: #011729;
}
.c-hamburger[aria-expanded="true"] .c-hamburger__line::before {
-webkit-transform: rotate(45deg);
-ms-transform: rotate(45deg);
transform: rotate(45deg);
}
.c-hamburger[aria-expanded="true"] .c-hamburger__line::after {
-webkit-transform: rotate(-45deg);
-ms-transform: rotate(-45deg);
transform: rotate(-45deg);
}
jQuery を使っています。
$(function(){
$("#hamburger-btn").on("click", function() {
$("body").toggleClass("is-drawerActive");
if ($(this).attr('aria-expanded') == 'false') {
$(this).attr('aria-expanded', true);
} else {
$(this).attr('aria-expanded', false);
}
});
}) ();
3本線のボタンを作成する
正解があるのか分かりませんが、 button 要素を選択した理由の1つは「キーボードで操作できる」というところにあります。
3本線を描くだけであれば、 span 要素や div 要素を使って描くことができますが、これらの要素にはフォーカスがあたりません。 HTML の要素の中でフォーカスのあたる要素は、基本的に a 要素とフォームのコントロール要素だけになります。
以前参考にさせていただいたハンバーガーメニューは、チェックボックス( input 要素)や label 要素を使用したものでしたが、ここではキーボードでも操作できるということで button 要素を使っていきます。
完成した部品には、「 aria-expanded 」や「 aria-controls 」などの属性が付加されていますが3本線を引くだけであれば次のタグと CSS のみで作成することができます。3本線の「線」の部分は、 span 要素で描きます。
<button class="c-hamburger">
<span class="c-hamburger__line">
</span>
</button>
この例では、 38px のボタンを作成します。 position:relative; は、疑似要素の位置を決めるために必要になるので定義しておきます。ボタン自体は、見える必要が無いため border や outline を none に設定し枠線や影を消しておきます。
.c-hamburger {
position:relative;
width: 38px;
height: 38px;
border: none;
outline: none;
background: transparent;
}
次に「線」を1本引きます。幅 18px , 高さ 2px のボックスを作り背景色を設定します。 margin: auto; とすることでセンターリングされ、1本の線が描かれます。
.c-hamburger__line {
position: absolute;
display: block;
top: 0;
right: 0;
bottom: 0;
left: 0;
margin: auto;
width: 18px;
height: 2px;
background-color: #011729;
}
ハンバーガーメニューに必要な線は3本なので残りの2本は、疑似要素を before と after で用意します。疑似要素は、上下に 5px ずらすことで3本の線となるよう設定します。
.c-hamburger__line {
position: absolute;
display: block;
top: 0;
right: 0;
bottom: 0;
left: 0;
margin: auto;
width: 18px;
height: 2px;
background-color: #011729;
}
.c-hamburger__line::before,
.c-hamburger__line::after {
content: '';
position: absolute;
display: block;
width: 100%;
height: 100%;
background-color: inherit;
}
.c-hamburger__line::before {
top: -5px;
}
.c-hamburger__line::after {
top: 5px;
}
ここまでで3本線のボタンが用意できます。
ハンバーガーメニューをアニメーションさせる
ハンバーガーメニューを変形して閉じるボタンを作成します。ここでは、 aria-expanded という属性を使いますが aria-controls 属性や aria-expanded 属性は WAI-ARIA (Web Accessibility Initiative – Accessible Rich Internet Applications) というアクセシビリティを向上させるための属性になります。
最低限必要なものだけを書くと次のような HTML になりますが aria-expanded だけでは「何が expanded されているんだ?」となってしまうので、本来であれば aria-owns 属性や aria-control 属性等で展開される要素を明示する必要があります。
とりあえず、動作確認を単純化するため次のような HTML にしています。
<button id="hamburger-btn" class="c-hamburger" aria-expanded="false">
<span class="c-hamburger__line">
</span>
</button>
ハンバーガーメニューをクリックする都度、aria-expanded 属性を変更したいので次のような JavaScript を用意します。 id 属性 hamburger-btn のボタンがクリックされると、 aria-expanded 属性の値が true / false でトグルします。
$(function(){
$("#hamburger-btn").on("click", function() {
if ($(this).attr('aria-expanded') == 'false') {
$(this).attr('aria-expanded', true);
} else {
$(this).attr('aria-expanded', false);
}
});
}) ();
aria-expanded 属性が true になった時、中央の線を透過して上下2本の線を45度回転させます。アニメーションさせるため transition に all .3s ease-in-out と設定し、aria-expanded 属性が true の時に中央の線が見えなくなるよう background-color: transparent; を指定します。疑似要素にそれぞれ45度と-45度回転するように指定することで閉じるボタンに変形します。
.c-hamburger {
position:relative;
width: 38px;
height: 38px;
border: none;
outline: none;
background: transparent;
outline: none;
-webkit-transition: all .3s ease-in-out;
transition: all .3s ease-in-out;
}
.c-hamburger__line {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
display: block;
margin: auto;
width: 18px;
height: 2px;
background-color: #011729;
-webkit-transition: inherit;
transition: inherit;
}
.c-hamburger__line::before,
.c-hamburger__line::after {
content: '';
position: absolute;
display: block;
width: 100%;
height: 100%;
background-color: inherit;
-webkit-transition: inherit;
transition: inherit;
}
.c-hamburger__line::before {
top: -5px;
}
.c-hamburger__line::after {
top: 5px;
}
.c-hamburger[aria-expanded="true"] .c-hamburger__line {
background-color: transparent;
}
.c-hamburger[aria-expanded="true"] .c-hamburger__line::before,
.c-hamburger[aria-expanded="true"] .c-hamburger__line::after {
top: 0;
background-color: #011729;
}
.c-hamburger[aria-expanded="true"] .c-hamburger__line::before {
-webkit-transform: rotate(45deg);
-ms-transform: rotate(45deg);
transform: rotate(45deg);
}
.c-hamburger[aria-expanded="true"] .c-hamburger__line::after {
-webkit-transform: rotate(-45deg);
-ms-transform: rotate(-45deg);
transform: rotate(-45deg);
}
メニュー等の表示
後はクリックされた時のメニューをどう表示するかですが、aria-controls 属性に指定した drawer という id の要素を閉じたり開いたりさせます。この動作のトリガーに次の JavaScript を使用して body 要素の is-drawerActive 名をトグルさせます。
クラス名 is-drawerActive の有無でメニューを開いたり閉じたりすれば完成です。
$("body").toggleClass("is-drawerActive");