マークアップエンジニアとかWEBディレクターとかをやってる僕が、自分が詰まって、解決したことをここに残しておきますよ。

androidでも速いハンバーガーメニュー(開閉メニュー)をつくる

スマホといえば、もう最近はほぼハンバーガーメニューだよね。
タップで上から降りてくる。
バツボタンをタップでまたあがっていく、というような。

普通につくると、以下のようにやりたくなる。

$('header nav').css({"top":"-1000px"});
$('#openMenu').click(function(ev){
ev.stopPropagation();//①
$('header nav').height($(window).height());//②
$('header nav').animate({top:0});//③
$('body,html').css({"overflow":"hidden","height":"100%"});//④
}); 

あらかじめ上のほうにメニューをふっとばしておいて、
#openMenuボタンをクリックしたらanimateでtop:0まで降りてくる。 

細かく説明すると、
①android対策等で親要素にクリックが伝搬しないようにする
②降りてくるメニューはウィンドウと同じ高さにセット(必要に応じて使う)
③メニューをtop:0の一までおろしてくる
④メニュー内をスワイプしてるときに背景がスクロールしちゃうのを防ぐ

わりとシンプル。
iphoneだけならこれでも全然いい。

※閉じるの処理はちょっと割愛してます。


でもandroidだと

「なんか遅いんですけど」
とか言われたりする。

そういうときは、めんどくさいけど、css3でアニメーションさせることになる。

んで作ったのが以下の様な感じ。

css

header nav{
width:100%;
top:-1000px;
overflow:scroll;
transform:translate(0px,0px);
-webkit-transform:translate(0px,0px);
transition: transform 0.3s ease-out;
}

header nav.on{
transform:translate(0px,1000px);
-webkit-transform:translate(0px,1000px);

js

$('#openMenu').on('click',function(ev){
ev.stopPropagation();
$('header nav').height($(window).height());
$('header nav').addClass('on');//⑤
$('body,html').css({"overflow":"hidden","height":"100%"});
}); 

jsはもともとのとほとんど同じだけど、animateで動かしてたのを消して、addClassだけになった。
⑤class="on"をnavタグにつける。

そしてアニメーション処理をやらせてるのは、cssのほう。

transitionでアニメーションで動くようにして、
.onがついてるのとついてないので、transform:translate(x,y)の位置を変えるという処理。

※閉じるの処理は割愛


 androidでtransformが効かなくて30分ほどロスしたけれども、ただ-webkit-プレフィクスをつけるだけだったという。

注意ですわね。 

スマホでメニューを開いた時に後ろはスクロールしないようにする

地味にはまってしまった。

スマホサイトのメニューって大体ハンバーガーメニューだよね。最近は。

38
(ハンバーガーメニューというやつ)

これをタップすると、ズルーっとグローバルメニューがかぶさるようにおりてくる、というのが一般的。

さて、そのメニュー内をスワイプしていると、後ろ側の ページが動いてしまうという現象に悩まされた。
タップでスクロールを禁止させるというのも見つけたが、
メニュー内はスクロールできるようにしたいため、背景だけスクロールを不可にしたい。


んで、しらべてみたら、htmlとbodyに対して、height:100%とoverflow:hiddenを割り当てればよいということがわかった。

実際に書くとこんな感じ。
閉じるときは解除も忘れずに。

$('#openMenu').click(function(){
$('header').fadeIn();
$('body,html').css({"overflow":"hidden","height":"100%"});
});
$('#closeMenu').click(function(){
$('body,html').css({"overflow":"visible","height":"auto"});
$('header').fadeOut();
});

手持ちのiphone6ではうまくいっている様子。

-------------追記-------------------

htmlも見たいというコメントをいただいたのでサンプルのhtmlのせますね。

<header>
<div class="headerInner">
<div class="headerLogo">
<h1><img src="img/logo.png" alt="ロゴ"></h1>
</div>
<a href="#" id="openMenu"><img src="img/icon_menu_sp.png" alt="menu"></a>
</div>
<nav class="gnav">
<ul>
<li><a href="#">メニュー</a></li>
<li><a href="#">メニュー</a></li>
<li><a href="#">メニュー</a></li>
<li><a href="#">メニュー</a></li>
<li><a href="#">メニュー</a></li>
</ul>
<a href="#" id="closeMenu"><img src="img/icon_menu_sp.png" alt="menu"></a>
</nav>
</header>

 今回のサンプルだとこんな感じ。

開くボタンと閉じるボタンがわかれてるパターン。
(開くも閉じるも1つのボタンっていうパターンも多いのでそれはまた別の記事で)


レスポンシブで動的に高さ変更したときの解除

レスポンシブでの要素の高さ変更などは、普通はcssで行うよね?

pcではheader{height:90px}

で、

spではheader{height:200px}のように。 


でもspではメニューが上からズルっと降りてきたりして、その際に、hightが動的に書き換える処理になったりする。

var winH = $(window).height();
$('height').height(winH);

のように。


すると、html側では、headerにstyle属性がつく。


その状態でウィンドウサイズをpcに戻したりすると、cssで指定したheight{90px}よりもstyleで書かれた動的な高さが適用されてしまう。

そういう場合にどうしたらいいのかなって考えてたんだけど、

いったん今のところの解決は、

pcになったらstyleをカラにしちゃうってことかな。と。


if(winsize > hogehoge){ // pcになったら
$('header').attr('style','');
}


って感じで。


※removeAttr()なるjQueryメソッドもあるらしいんだけどこれをやると、今度はsp側で動的に変更ができなくなるので使えなかった。
 
記事検索

リモキュー

お仕事のご依頼・お問い合わせはこちら

コーディングのお仕事が得意です。

https://twitter.com/tacshock
タグクラウド
QRコード
QRコード
  • ライブドアブログ