EdgeとIE11のバグと対処法~animationと@keyframesのheight:auto;編
スクリプトでメニューとか作る際、CSSでanimationと@keyframesを動的に書き出しているときにEdgeとIE11を見ていて気付いてハマったこと。
こいつらでCSSのanimationが使えるようになったのは嬉しいことで、メニューとかの展開にわざわざJavaScriptでフレーム処理かけなくても終端の値さえ算出すればなめらかなアニメーションができるようになった。
そして、終端値を設定した後、最後のフレームでheight:auto;すればclassやstyleをパターンごとにガチャガチャ切り替えなくてもシンプルなコードで書けるようになった。
昔からスクリプトでメニューのコードを書いていた自分にとってはこれはとても画期的で、普段使いのブラウザであるChrome・Firefoxと同じことがMicrosoftのブラウザでできるのは改良だな~と思っていた。
(以前にこちらの記事を書いたときのバグで相変わらずEdgeは辟易しているが。)
・・・いたのだが。
はい。またEdgeさんもIE11さんもやらかしてくれました。
やはりお家芸を通り越して伝統とも呼べる特有のバグ。
animationと@keyframesのバグの事例。
これらを利用してメニューの展開用のスクリプトを作るため以下のようなコードを書いた。
/* CSS */ .menu.menu-opened{ overflow:hidden; animation-name: menu-open; animation-timing-function: cubic-bezier(0.19, 1, 0.22, 1); animation-fill-mode: forwards; animation-iteration-count: 1; animation-duration: 0.5s; } // スクリプト側に記載したコード @keyframes menu-open{ 0%{ height: 0; } 99%{ height: 【スクリプトで動的に変更する終端値】px; } 100%{ height: auto; } }
そしてブラウザ側でのチェック。
いずれもメニューボタンを押したときのメニュー展開中。
見ての通りEdgeとIE11は展開されてない・・・。
というか、アニメーションそのものが発生しなかった。
おいおい、冗談だろう・・・。
動きを見る限り、EdgeとIE11では@keyframesの中のheightの最終的な設定値がautoだと、他のフレームでheightの数値を指定していようが全てが無効な値として扱われてしまうようだった。(やってはいないが恐らくwidthとかも同じだと思う。)
試しに100%のフレームのheight:auto;をinheritとか数値に変えた場合はメニューの展開は行われた。
でもこれだと非常に拙い。
スクリプトだけでメニューのコード書いているときもそうだったが、当然、メニューの中身が増減したりツリー表示で縦に伸び縮みすることも考慮しなければならない。
そのため、何としても最終的なheightはautoにしなければならない。
・・・どうにかできないかと思い、CSSをいじくって試行錯誤しているときに偶然発見した対処法。
animationと@keyframesを以下のように書いてみた。
// CSS .menu.menu-opened{ overflow:hidden; height: auto; /* 追加 */ animation-name: menu-open; animation-timing-function: cubic-bezier(0.19, 1, 0.22, 1); animation-fill-mode: forwards; animation-iteration-count: 1; animation-duration: 0.5s; } // スクリプト側に記載したコード @keyframes menu-open{ 0%{ height: 0; max-height: 0; // 追加 } 99%{ height: 【スクリプトで動的に変更する終端値】px; max-height: 【スクリプトで動的に変更する終端値】px; // 追加 } 100%{ height: auto; max-height: 99999px; // 追加 } }
max-heightを併記してみると・・・。
そのとき、IE11とEdgeの身に不思議なことが起こった。
メニューがきちんと展開されたではないか!
なんかよくわからないけどよかったよかった!
・・・何となくできただけでは、コピペコードと何ら変わらないので紐どいていく。
以下は、対処法のコードの実際に何が起きているか?の流れ。
- 「.menu.menu-opened」がスクリプト側でclass=””に追加された時点で、height:auto;になる。
これだけだとメニューは全表示状態だが、0%のフレーム内でmax-heightを0として取っているので、実体の高さは0となり、アニメーションがスタートされる。
100%のフレーム内のheightは最終的な設定値がheight:auto;なので(EdgeとIE11に限り)終始無視される。 - 99%のフレームまでmax-heightをベースとしてアニメーションは終端値まで動いていく。
他のブラウザではheightとmax-heightが同じ値でアニメーションしていく。 - 100%のフレームでmax-heightは9999pxとなりメニューは全表示状態となる。
このとき、「.menu.menu-opened」でheight:auto;なのでmax-heightで取った9999pxまでは可変。
9999pxはメニューの中身の増減を含めて全表示状態にできる値であればなんでも良い。
以上。まさか年明けからブラウザのバグに悩まされるとは・・・。
あ、今更ですが。
あけましておめでとうございます。
本年もよろしくお願い致します。
そして、遅ればせながら12月中旬ごろにコメントしていただいた方、ありがとうございました。