スマホサイトでよく使われるドロワーメニュー。ハンバーガーボタンをタップすると、画面の端からにゅるっと出てくるあの仕様です。便利な反面、実装方法によっては、ブラウザの「戻る」ボタンで前のページに戻ったときに、一瞬ドロワーメニューが表示されてしまうことがあります。
結論から言うと、この問題はドロワーをtransformで隠すのではなく、position(rightなど)で隠すことで解決できます。この記事では、一般的な実装の仕組みと、なぜ一瞬表示されてしまうのか、その対処法を解説します。
よくある実装では、ドロワーメニューをtransformで画面外に逃がして隠しておきます。
.drawer-menu {
transform: translate(-300px);
}
そして、ハンバーガーボタンをタップしたときにopenなどのクラスを追加し、そのクラスでtransformを上書きして、メニューを画面内に表示させます。
.drawer-menu.open {
transform: translate(0);
}
transformにtransitionを組み合わせると、なめらかにスライドインする動きになります。多くのドロワーメニューがこの仕組みで作られています。
このtransformを使った実装だと、ブラウザの「戻る」ボタンで前のページに戻ったときに、閉じているはずのドロワーメニューが一瞬だけ表示されてしまうことがあります。
これは、ブラウザが「戻る」で表示するページを高速化のためにキャッシュから復元する際、transformとtransitionの初期状態がうまく反映されず、閉じる動きが一瞬見えてしまうために起こります。ユーザーからすると、意図せずメニューがちらついて見えるため、あまり気持ちのよいものではありません。特にiOSのSafariで起こりやすく、ページを離れる際のドロワーを閉じるアニメーションが、戻ってきたときに再生されてしまうイメージです。
解決策は、transformを使わず、positionのプロパティ(rightなど)で画面外に逃がす方法です。まず、ドロワーをrightのマイナス値で隠しておきます。
.drawer-menu {
right: -300px;
}
そして、openクラスが付いたときにright: 0にして表示させます。
.drawer-menu.open {
right: 0;
}
この書き方に変えると、戻るボタンで戻ったときのちらつきが解消されます。rightの変化にtransitionを効かせれば、transformのときと同じようにスライドインの動きも再現できます。
transformは、描画の負荷が軽くアニメーションが滑らかという利点があり、通常はスライド系の演出に向いています。ただ、今回のように「戻る」でのページ復元と相性が悪い場面もあります。
どうしてもtransformを使いたい場合は、ページ復元時に発火するpageshowイベントで、いったんアニメーションを無効にして状態をリセットする、といった対処もあります。まずはシンプルにpositionで解決し、要件に応じて使い分けるとよいでしょう。
あわせて覚えておきたいのが、読み込み直後のちらつきを防ぐ一般的な手法です。ページの読み込み時はtransitionを無効にしておき、表示が安定してからアニメーションを有効化する、という方法です。たとえばbodyにno-transitionのようなクラスを付けておき、load後に外す、といった実装が使えます。ドロワーに限らず、初期表示のアニメーション暴発を抑えたいときに役立ちます。
transformで隠したドロワーは、戻るボタンで一瞬表示されることがあるtransformではなくposition(rightなど)で隠すと解消できるtransformを使うならpageshowイベントでの状態リセットも手transformは便利なプロパティですが、状況によっては思わぬ挙動を招きます。ちらつきが気になったときは、隠し方をpositionに変えてみてください。