CSS3のアニメーションで動くドロワーをプラグイン無しで実装してみる

スマホサイトやアプリでよく見るUIのドロワーを実装したい。しかしjQueryのメソッドで動かせばスマホでの挙動が重いので、CSS3のアニメーションで実装してみます。ドロワーを実装する方法は他にも色々あると思いますが、そのうちの1つということで。

ドロワーをCSS3とjQueryで実装

今回実装するドロワーの仕様はこんな内容です。

  • ボタンのタップ、クリックでドロワー表示用クラスをjQueryで付ける
  • ドロワー表示時にドロワー以外の領域もしくはボタンをタップ、クリックしたら閉じる
  • IE9以下でのアニメーションは諦め、最低限の機能を提供するようにする

プラグインを使わずに、なるべくjQueryでの処理を増やさないというコンセプトなのでHTML構造はちょっと依存します。今回ご紹介する方法で実装したドロワーのデモはこちらで確認できます。

css-transition-drawer01
画像で説明するとこんな感じです。ボタンを押したらドロワーを表示します。

HTML部分

まず、HTMLはこのようにします。ドロワーはラッパー要素と分離します。

クラスoverlayが付いたdivタグは、ドロワーが開いたときにラッパー部分を暗くするために使います。

CSS部分

CSSで重要な部分はtransitionによるアニメーション指定と、transformのtranslateプロパティによる要素の移動です。

肝の部分のみ書くとこんな感じになります。まずラッパー要素。

 

次にドロワー要素です。

jQueryでボタンがタップされたら各々の要素にクラス「open」を付けること前提にCSSを書きました。

jQuery部分

jQueryでは、ボタンが押されたらopenクラスをドロワー要素とラッパー要素に追加する処理をします。

変数にあらかじめコンテンツ(#wrapper)、ドロワー(#drawer)、ボタン(#drawer-toggle)を格納して、それらにon()メソッドでスマホとPCでのタッチ、クリックイベントを割り当てています。

これでドロワー用クラスのON/OFFが切り替えられるようになり、実装完了です。

2014年10月5日追記:

コンテンツ部分をタップした時の処理も「return false;」と書いていましたが、これではURLが設定されたaタグをクリックした時にページ移動しなくなってしまうので、イベント伝播のみ阻止する「stopPropagation()」に変更しました(上記ソースコード23行目)。

 IE9以下はプログレッシブ・エンハンスメントで対応

IE9以下で通常の動作にならない点はtransitionが効かない他「translateで移動しない」、「オーバーレイのrgbaがIE8以下で効かない」の2つがあります。オーバーレイの半透明色とtransitionのアニメーションは使用上問題無いとして、ドロワーが表示されないのは痛いです。なので、IE9以下には別のCSSで対応してみます。

まず、Internet Explorer独自仕様の条件付きコメントを使い、IE9以下だった場合に<html>タグに専用のクラスを付けます

これでクラス「lt-ie9」をCSSで使えばIE9以下でのみのスタイリングができるようになります。ラッパー要素とドロワー要素でこのクラスを使った結果がこちらです。

代替案としてそれぞれの要素をrightプロパティで移動させることにしました。これでアニメーションはしませんが、一先ずドロワーを開けるようになり最低限の機能が提供できるようになりました。

ドロワー実装時につまづいたこと

最後に、このドロワーを作った時につまづいたことを3つ挙げておきます。

要素の移動にはtranslate3dを使った

positionの位置を変更するだけでも可能ですが、アニメーションするときにラッパーとの動作が一致しない(隙間が一瞬できたりする)ことがありました。結果安定感のあるtranslate3dを使っています。(詳しい原因は分かっていません…)

translateは3D版を使う

translateは2D版ならIE9でも動くのですが、スマホ(iphoneのsafariで確認)だと2D版はなぜかドロワー自体が消えたりしました…。fixedとの相性なのでしょうか。

IE9ではアニメーションが効きませんし、それならもう3D版に統一しようという結果に。

jQueryでのボタンクリックイベントが親要素にも伝播した

今回で言えばドロワーを表示するボタンはラッパー要素の中に入っているのですが、このラッパーにもイベントを割り当てていました(ドロワーを閉じる処理)。すると、子要素(ボタン)をクリックしたときに親要素(ラッパー)までもがイベント処理をし始めたんです。どうやらjQueryには親要素にもイベントが伝播する性質があるようで、これにハマりました。

親要素にイベントを伝播させないため、またaタグのURLクリックで画面遷移させないために「return false;」を追加しました。参考なった記事はこちらです。

子要素のイベント後、親要素のイベントも発生してしまう|teratail

1分でわかるreturn false; preventDefault(); stopPropagation() の違い | iwb.jp

最終更新日:2014年10月8日

コメント

「何かそこ違うよ」「こうした方が良い」っていう部分があったら指摘して頂けると嬉しいです。

トラックバック

トラックバックは現在ありません。

Trackback: https://increment-log.com/css-transition-drawer/trackback/