ふんばりフロントエンジニアのブログ

新米フロントエンジニアのふんばっている日々と備忘録です。

displayにtransition効かないんだけどどうすんだよ…【対処法】

cssで最近「なるほど!」って思ったことを一つ。

transitionプロパティって便利ですよね。

知った当初は何にでもtransitionつけて「カッケエ...」とか思ってましたが、もちろん万能ではありません。

特に「display+heightでheightにtransitionつけたらいい感じのアコーディオンとか作れんじゃね?」って思った方も少なからずいるでしょう。

ただ、それを実現するには少し工夫が必要かもしれません。

codepen.io

今回作成したのは単純なアコーディオンです。

中のコンテンツ(ここでは.inner)のdisplayをnoneかblockにするクラス「accordion」とheightを変えるクラス「active」をjsのclassListで追加している訳なのですが、ここで私最初に「displayとheightの処理を一つのクラスにまとめて、heightにtransitionかけたらいけんじゃね?(浅はか)」と思ったのです。

まあご存知の方はお分かりかと思いますが、結論から言うと無理ですよね。

と言うのも、まずdisplayプロパティとは言ってしまえば存在自体を消すかどうか、というプロパティです。

同じ目に見えなくなるものとして、opacityがありますがここがopacityとは違う点ですよね。

このような実例を検索するとopacityとheightで実装、という例が出て来ますが私はどうしてもdisplayを使いたかった…(というよりopacityは結構使いどこ難しい気がする…

ということで、今回重要なポイントは二つ!

①displayとheightの制御クラスを二つに分ける

②setTimeout関数

「なんで分けんだよ!!!!」とお思いかもしれませんがこれが結構重要です。

まずdisplayの話に戻りますが、displayは存在を消してくれるプロパティ。

つまり「display:none」にすると、ブラウザにも認識されなくなってしまいます。

そのような要素に「heightを伸ばすんじゃボケ!」と言っても「はあ?」となってしまいすよね。

ただ、displayを表示してから「heightを伸ばすんじゃ!」と言えばあちらさんも鬼ではないのできっちり理解してくれます。

ただ、普通に同じクラスでdisplayとheightを指定していたのでは理解されるタイミングが一緒なので「はあ?」状態になってしまう訳ですよね。

そこで出てくるのがポイントにあげた二点!

まず、displayをblockにするクラスとheightを変えるクラスを作ります。

二つクラスを追加することによってどこでどっちのクラスを追加するか、という選択肢が生まれてきます。

なのでまずはじめにdisplayを制御するクラス「active」をOPENがクリックされたら追加するようにし、setTimeout関数でその10ミリ秒後にheightを変えるクラス「accordion」を追加するようにしている訳です。

これならしっかりどの要素の高さを変えるのか、ということは理解してくれます。

結論としては、display+heightで指定してるからtransitionが効かないのではなく、一緒に指定しているとdisplayがnoneの状態からheightのプロパティも認識されてしまうためtransitionが効かなくなってしまうんです。

タイミングを10ミリ秒ずらすだけでもheightに対するtransitionは効かせることができます。

これはランドスケープした時にどうこうする...とかOSやブラウザでイベントのタイミングが異なる時にも利用されがちな仕組みです。

灯台下暗し感が強い内容でしたが、displayを使っても実装できるのは自由度が高くていいですよね〜〜