スマホ向けナビゲーション(メニュー)では、三本線のアイコンをタップする設計がスタンダードになりました。
ここでは、PC・スマホ兼用を前提とし、ウィンドウサイズでCSSで切替えるレスポンシブ・ウェブ・デザインによる三本線メニューの実装方法を考えてみます。
尚、まめわざではこの方法を採用していませんが、近いうちに実装予定です。
という想定でサンプルを作成しました。
サンプルその1は三本線アイコンをタップした際にクラスをセットすることで、その2はCSSの:hoverを利用することで隠れたメニューを表示しています。
レスポンシブなので、ウィンドウ幅を変えてご確認下さい。
<div class="title">
<h1>テストページ</h1>
</div>
<div class="wrap">
<div class="side">
<div class="menu3bar" onclick="menu3bar(this)">
<span class="menu3bar"></span>
<ul>
<li><a href="#">1番目のメニュー</a></li>
<li><a href="#">2番目</a></li>
</ul>
</div>
</div>
<div class="contents" style="height:2000px;background-color:#eee;"></div>
</div>
骨格は
<div class="title"></div>
<div class="wrap">
<div class="side"></div>
<div class="contents"></div>
</div>
というシンプルなものです。
sideの中に入っている
<div class="menu3bar" onclick="menu3bar(this)"></div>
がメニューの本体です。
<span class="menu3bar"></span>
は三本線アイコン、
<ul></ul>
はメニューの中身で、ネスト(入れ子)の表現も想定しています。
/*タイトル*/
div.title {
padding: 5px 30px;
text-align: center;
}
div.title h1 {
margin: 0;
font-size: 200%;
}
/*pc用スタイル*/
@media only screen and (min-width: 1024px) {
div.wrap {
display: -webkit-flex;
display: flex;
}
div.side {
-webkit-flex-basis: 300px;
flex-basis: 300px;
}
div.contents {
-webkit-flex: 1;
flex: 1;
}
}
/*三本線メニューのアイコン*/
span.menu3bar {
position: absolute;
right: 10px;
top: 10px;
display: inline-block;
width: 15px;
height: 15px;
outline: 1px solid #999;
background-color: #999;
border: 5px solid #fff;
vertical-align: middle;
}
span.menu3bar:before, span.menu3bar:after {
position: absolute;
content:"";
display: block;
top: 20%;
right: 0;
height: 20%;
left: 0;
background-color: #fff;
}
span.menu3bar:before {
top: 20%;
}
span.menu3bar:after {
top: 60%;
}
/*pc用スタイル*/
@media only screen and (min-width: 1024px) {
span.menu3bar {
display: none;
}
}
/*メニュー*/
div.menu3bar ul {
margin: 0;
padding: 0;
list-style: none;
}
div.menu3bar > ul {
position: fixed;
top: 0;
right: -100%;
max-width: 70%;
max-height: 100%;
background-color: #fff;
background-color: rgba(255, 255, 255, 0.8);
text-align: left;
overflow: auto;
font-size: 80%;
line-height: 160%;
-webkit-overflow-scrolling: touch;
-webkit-transition: right .3s ease-in-out;
transition: right .3s ease-in-out;
}
div.menu3bar > ul > li {
margin: 0;
padding: 10px;
border-bottom: 1px solid #eee;
}
div.menu3bar > ul ul {
margin-left: 10px;
}
div.menu3bar > ul ul li {
padding: 5px;
}
div.menu3bar_on > ul {
right: 0;
}
/*pc用スタイル(例)*/
@media only screen and (min-width: 1024px) {
div.menu3bar > ul {
position: static;
max-width: none;
overflow: visible;
}
}
今回はモバイル向けの表示ということで、基本スタイルをモバイル向け、メディアクエリで
@media only screen and (min-width: 1024px) {}
としてPC向けのスタイルを定義しています。
メニューの入れ物である、
div.menu3bar
は、三本線アイコンクリック時にmenu3bar_onクラスを付与しています。
この時、
div.menu3bar > ul {
right: -100%;
}
が
div.menu3bar_on > ul {
right: 0;
}
となることで、右側からメニューが現れます。
transitionを使って右側からゆっくりと登場するアクションを表現しています。
span.menu3bar
は三本線アイコンをCSSで表現しています。
サンプルではbodyからの絶対指定でアイコンを表示し、div.titleの右側にpaddingをセットして、アイコン表示域を空けています。
PC用スタイルでは、三本線アイコンを非表示化し、また
position:fixed
でコンテンツの上に表示していた三本線メニューの本体を、
position:static
にしてdiv.side内に表示しています。
var menu3bar_off = function(e) {
var elm = e.target ? (e.target.nodeType == 3 ? e.target.parentNode : e.target) : (window.event.srcElement ? window.event.srcElement : "");
if(!elm || $(elm).parents(".menu3bar")[0]) {
return "";
}
$(document.body).unbind("touchend", menu3bar_off);
$(document.body).unbind("click", menu3bar_off);
$(".menu3bar_on").removeClass("menu3bar_on");
};
var menu3bar = function(self) {
if($(self).hasClass("menu3bar_on") ) {
return "";
}
$(self).addClass("menu3bar_on");
$(document.body).unbind("touchend", menu3bar_off).bind("touchend", menu3bar_off);
$(document.body).unbind("click", menu3bar_off).bind("click", menu3bar_off);
};
$(document).ready(function() {
if(navigator.userAgent.indexOf("Android 2.") === -1) {
return "";
}
$("div.menu3bar > ul").css( {
"position": "absolute",
"max-height": "none",
} );
} );
jQueryを利用しています。
menu3bar
menu3bar_off
の両関数は、div.menu3barをクリックした際に、menu3bar_onクラスを付与し、menu3bar以外の場所をクリックした際に、menu3bar_onクラスを解除する処理をしています。
念のためにclickとtouchendにセットしています。
ページ読み込み時に、ユーザーエージェントチェックを行い、Android2.x系の場合は、三本線メニューの本体のpositionをfixedからabsoluteに変えることで、クロスブラウザ化しています(Android2.x系では、三本線メニューが画面に入り切らない場合に、overflow:autoでスクロールして表示できないため)。
Android2.xを対象にしない場合はこの箇所は不要です。
下記のようにHTML・CSS・Javascriptの一部を差し替えて、ほぼCSSだけで実装したバージョンです。
Javascriptはbodyに付与したontouchstartと空のdummy()関数のみです。iOSでタップ時に:hoverのアクションを発動させるためにこれらが必要であり、CSSだけの実装はできません(この部分が解決すれば、AMPでの利用もできそうなので期待していますが、今のところJavascriptなしでの実装はできていません)。
<body ontouchstart="dummy()">
<div class="title">
<h1>テストページ</h1>
</div>
<div class="wrap">
<div class="side">
<div class="menu3bar">
<span class="menu3bar"></span>
<ul>
<li><a href="#">1番目のメニュー</a></li>
<li><a href="#">2番目</a></li>
</ul>
</div>
</div>
<div class="contents" style="height:2000px;background-color:#eee;"></div>
</div>
</body>
割愛(前述のCSSを次の差し替え箇所の通りに変更して下さい)。
div.menu3bar_on > ul {
right: 0;
}
↓
div.menu3bar:hover > ul {
right: 0;
}
function dummy() {
}
ご自由にご利用いただけます。改変OK、報告不要です。気に入っていただけたらシェアをお願いいたします。
iOSで:hoverアクションのトリガーとしてontouchstartを使っていますが、Javascriptを使わない代替案がありましたらぜひ教えてください。よろしくお願いいたします。