search
LoginSignup
21

More than 1 year has passed since last update.

posted at

updated at

Organization

アコーディオンの開くアニメーションをCSSで表現する

久しぶりにフロントエンド周りです。
ボタンを押すとアコーディオンが開く、というよくある実装を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

ezgif.com-gif-maker.gif

全くうまくいっていないのがわかるかと思います。
これは、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

ezgif.com-gif-maker (1).gif

つまづきやすいポイント2: padding

max-heightを調整したのに、開いていない状態でも高さが残ってしまう...なんて場合は、paddingを考慮し忘れているかもしれません。

.foo
  max-height: 0
  padding: 20px
  transition: max-height 0.2s
  overflow: hidden
  &.is-open
    max-height:100vh

↓閉じた状態にもかかわらずpaddingが残っているとこうなる
スクリーンショット 2021-06-10 15.27.21.png

ではpaddingを全部消せば良いのかというと、左右paddingをショートハンドなどで巻き込んでしまっていると、
徐々に左右のpaddingが出てしまうという変な動きになってしまいます。

// 左右のpadding変な動き
.foo
  max-height: 0
  padding: 0
  transition: max-height 0.2s, padding 0.2s // ここにpadding-leftpadding-rightも入っている
  overflow: hidden
  &.is-open
    max-height:100vh 
    padding: 20px

ezgif.com-gif-maker (1).gif

解決方法としては、

  • 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

ezgif.com-gif-maker.gif

これで実現したい動きを実装できました🎉

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
21