GoogleモバイルサイトやDisney.comのオフキャンバスっぽいメニュー
公開:
更新:
Googleのスマートフォンサイトがリニューアルされたというので見てみたら、メインメニューの表示方法が面白い感じになっていたので自分でも作ってみました。
ちなみに、先日レスポンシブウェブデザインに変更したDisney.comも、表示幅が1024px以下だと似たようなメニューの表示方法になります。
作ったものは以下。
サンプルなのでHTMLは適当に。
実際にはもっと複雑になるでしょうが、動きを試すためのものなのでこんな感じで。
<div id="nav" class="globalnav">
<a href="#">Navigation</a>
</div>
<div id="main" class="content">
<div class="switcher">
<button id="toggleMenu">&#9776;</button>
</div>
Main Content
</div>
button#toggleMenu
をクリック(タップ)したらメニューの開閉を行います。
jQuery(function ($) {
$('#toggleMenu').on('click', function (e) {
e.preventDefault();
$('body').toggleClass('showMenu');
});
});
遷移アニメーションなどはCSS側でやるので、JavaScript側ではメニューが開いているかどうかという状況を判別するクラス名を付け外しするだけにします。
(サンプルでは使ってますが、特にjQuery使う必要はないです)
ではこの動きの肝であるCSSを。
.globalnav {
position: fixed;
top: 0;
left: 0;
z-index: -1;
width: 160px;
height: 100%;
background: #fcc;
visibility: hidden;
transition: visibility 0s linear 0.2s;
}
.showMenu .globalnav {
z-index: 1;
visibility: visible;
transition: z-index 0s linear 0.2s;
}
.content {
height: 900px;
background: #ccf;
transform: translateX(0px);
transition: transform 0.2s linear;
}
.showMenu .content {
transform: translateX(160px);
}
通常の状態(body
に特にクラス名を付与していない状態)では、div.globalnav
はvisibility: hidden
の指定により非表示となっており、position: fixed; z-index: -1
の指定でdiv.content
の下(レイヤー的な意味)にあって隠されています。
逆に言うとdiv.content
を被せることによって見えなくしているわけです。
メニューを表示している状態(body
にshowMenu
というクラス名が付いている状態)では、div.content
はtransform: translateX(160px)
によって、あらかじめ指定しておいたメニューの幅の分、右に移動します。
そしてメニューはvisibility: visible; z-index: 1
によってdiv.content
より上のレイヤーになって表示されます。
div.content
は普通にtransition: transform
しているわけですが、ここではtransition-duration
に0.2s
を指定しています。
この時間分、div.globalnav
のトランジションにディレイをかけます。
そうしないとbody
にクラス名showMenu
が付いた瞬間に一番上のレイヤーになってしまって見た目が悪いです。
メニュー部分のtransition-duration
が0s
なのは、これらは状態変化にディレイをかけるためで、遷移アニメーションさせるためのものではないからだと思われます。
メニュー部分は状態によって違うトランジションの指定を行います。body
にshowMenu
というクラス名が付いていないとき、つまり、閉じる動作のときにはvisibility
を対象とします。
これがないと閉じようとした瞬間にメニュー部分が見えなくなって見栄えが悪いです。
そもそもなぜここにvisibility
が指定されているのかということですが(なくても期待通りに動くのに)、おそらくAndroidのz-index
バグを回避するためだと思われます。重なった状態の下のレイヤー部分が反応してしますあれです。推測ですけど。
で、body
にshowMenu
というクラス名が付いているとき、開く動作の時にはz-index
をトランジションの対象にします。
こうすることによってvisibility: visible
は即座に反映されて、開いている途中でもメニュー部分が見えるようになります。そして開ききったらtransition-delay: 0.2s
によってz-index: 1
になって、メニューを一番上のレイヤーに配置します。
以上がGoogleのスマートフォンサイトの開閉メニューの仕組みです。たぶん。
ざっと見て作ったので実際のものとは結構違いがありますし、間違って解釈している部分があるかもしれません。
ちゃんと知りたい方は自分で確認してください。