久しぶりにフロントエンド周りです。
ボタンを押すとアコーディオンが開く、というよくある実装をCSSアニメーションを用いて実装します。
これが結末
.foo
max-height: 0
padding: 0 20px
transition: max-height 0.3s, padding 0.3s
overflow: hidden
&.is-open
max-height: 100vh
padding: 20px
つまずきやいポイント1: heightとtransition
最初に思いつきそうなのが、heightの高さを可変にして、transition
を使おう、というものだと思います。
.foo
height: 0
transition: height 0.2s
&.is-open
height: auto
全くうまくいっていないのがわかるかと思います。
これは、transitionがheightをサポートしていないからです。
ではどうすれば良いかと言いますと、いくつかの方法がありますが今回はmax-height
を使用する方向で実装します。
max-height
であればtransitionが効きます。
.foo
max-height: 0
transition: max-height 0.2s
overflow: hidden;
&.is-open
max-height:100vh // ここは適宜変更ください
つまづきやすいポイント2: display: none
display:none
から display: block
への変化などは、途中推移がないため当然transitionが効きません。
上記のようにmax-height
で指定してもうまくいかないので気をつけましょう。
max-hegihtとoverflowでコントロールしていれば、概ねdispalyでコントロールする必要はないパターンが多いかと思います。
どうしても非表示を行いたいケースではopacity
を使います。
この場合、伸び縮みだけではなく「ふわっとでる」ようになることに注意してください。
// ダメな例
.foo
display: none
max-height: 0
transition: max-height 0.2s
&.is-open
display: block
max-height: 100vh
// これならいける
.foo
display: none
transition: max-height 0.2s
max-height: 0
opacity: 0
&.is-open
display: block
max-height: 100vh
opacity: 1
つまづきやすいポイント2: padding
max-heightを調整したのに、開いていない状態でも高さが残ってしまう...なんて場合は、paddingを考慮し忘れているかもしれません。
.foo
max-height: 0
padding: 20px
transition: max-height 0.2s
overflow: hidden
&.is-open
max-height:100vh
↓閉じた状態にもかかわらずpaddingが残っているとこうなる
ではpaddingを全部消せば良いのかというと、左右paddingをショートハンドなどで巻き込んでしまっていると、
徐々に左右のpaddingが出てしまうという変な動きになってしまいます。
// 左右のpadding変な動き
.foo
max-height: 0
padding: 0
transition: max-height 0.2s, padding 0.2s // ここにpadding-left・padding-rightも入っている
overflow: hidden
&.is-open
max-height:100vh
padding: 20px
解決方法としては、
- transitionでの指定を律儀に
padding-top: ..``padding-bottom: ..
とする - 開いていない状態の上下paddingだけを削る
の二つがありますが、今回は後者で行きます。
.foo
max-height: 0
padding: 0 20px
transition: max-height 0.3s, padding 0.3s
overflow: hidden
&.is-open
max-height: 100vh
padding: 20px
これで実現したい動きを実装できました🎉