jQueryのslideUp() / slideDown()をCSS3で実現する

jQueryを使わずZepto.jsを使う時、もしくはライブラリを使わない時に、jQueryのslideUp()やslideDown()相当のことができないかと考えました。利用シーンは、例えばスマートフォン向けの画面で、ボタンを押すとメニューが下に開くウィジェットです。実現方法は、昨今のブラウザ環境も考えるとCSS3 Transitions(もしくはCSS3 Animation)を使えば良いかと考えました。

いざCSS3 Transitionsでやろうとしたのですが、CSS Transitionsの仕様書の7.1. Properties from CSS を見ると、heightはアニメーション可能なプロパティに入っていません。どうしようかと考えていたのですが、Stack Overflowを見るとCSS transition height: 0; to height: auto;という同じ悩みを抱えた人がいて、回答にmax-heightを使えば良いとありました。

サンプルを参考にしつつ自分なりに書いたところ、最終的には下記のようになりました。

See the Pen Toggle Menu by Hideki Abe (@hideki-a) on CodePen.

ポイント

  • max-heightを設定する
  • transitionで、開いた状態と閉じた状態のトランジションを設定する
  • JavaScriptでclass属性値を変化させる

max-heightの値が大きい場合の問題点

メニューの高さは様々な要因で変わる可能性があるので、それに備えてmax-heightを1,000pxといった大きな値に設定してみました。値が大きくてもIEやChrome、Androidのブラウザではまぁ良い感じにアニメーションしてくれるのですが(よく見るとおかしいです。開く時と閉じる時で速さが違います。)、Firefoxではパッと一瞬でスライドダウンしてしまうような感じでした。スライドアップの際もタイムラグが生じます。やはりきれいにアニメーションさせるには、適切な高さを設定しなければならないようです。

そこで今回は、1つdiv要素を追加し、スクリプト内で高さを取得してmax-height値として設定するようにしてみました。要素を追加せず高さを取得することもおそらく可能ではありますが、少し手間が増えます。

参考:WAI-ARIAの実装

参考までに、WAI-ARIAの実装もしてみました。WAI-ARIAを用いることで、ウィジェットがよりアクセシブルになります。

今回はボタンにaria-controls="menu"を設定し、nav#menuを制御していることを示しました。また、aria-expanded属性により、メニューが開いているか否かを表現することができます。これらの属性は、JavaScriptで設定・値の変更を行っています。

この記事のタグ