CSS 奇技淫巧:動態高度過渡動畫

ChokCoco發表於2021-01-13

這個問題源自於掘金上的一個留言,一個朋友問到,為什麼我下面這段程式碼的高度過渡動畫失效了?

虛擬碼大概是這樣:

{
    height: unset;
    transition: all 0.3s linear;
    will-change: height;

    &.up {
        height: 0;
    }
    &.down {
        height: unset;
    }
}

把它還原成一個實際的 Demo,效果大概是這樣(本質想的想法是通過給元素切換它的 .up.down 類,讓它實現展開、合上的動畫 ):

嗯哼?很奇怪,明明給 height 屬性設定了 transition,為什麼過渡動畫沒有觸發,而是直接一步到位展開了呢?

我們期待的效果是這樣的:

transition 不支援 height: auto

當上述程式碼設定成 height: unset 時,實際等同於設定了 height: auto,我們的想法是希望這段程式碼能夠容器支援文字的動態高度。每次展開的時候,過渡展開到容器本身的高度即可。

檢視規範,究其原因,在於 CSS transtion 不支援元素的高度為 auto 的變化。

如果把上述的 height: unset 替換成一個具體的高度值,則動畫是生效的,譬如:

{
    &.up {
        height: 0;
    }
    &.down {
      - height: unset;
      + height: 500px;
    }
}

但是,我們又希望能夠做到動態高度的過渡轉換,是不是就沒有辦法了麼?

 

巧用 max-height 適配動態高度

嘿嘿,這裡有一個非常有意思的小技巧。既然不支援 height: auto,那我們就另闢蹊徑,利用 max-height 的特性來做到動態高度的伸縮。

我們改造一下上述程式碼,將 height: 0 替換為 max-height: 0,將 height: auto 替換成 max-height: 1000px,虛擬碼大概是這個意思:

{
    max-height: 0;
    transition: max-height 0.3s linear;

    &.up {
        max-height: 0;
    }
    &.down {
        max-height: 1000px;
    }
}

我們估算一下實際容器的最大高度,這裡的 1000px 只需要比最大高度高即可。但是這裡不能設定的太高,最高是貼近最大的使用高度即可,後面會聊到為什麼。

由於 max-height 只是限制文字的最大高度,當容器的實際高度沒有達到限制的最大高度,將不會繼續變高,看看效果:

CodePen Demo -- the height property transition unwork

 

小缺陷

整體效果還是非常的 Nice 的,當然,可能有兩個小缺陷,

  1. 如果實際場景中 max-height 需要用到並且有其它作用,那麼可能這種方法就無法滿足需求了
  2. 另一個缺點就是視覺上有延遲,和實際高度相差越大越明顯。也就是說,如果容器實際高度只有 200px,max-height 為 1000px,動畫時間為 1s,緩動函式為 linear。實際動畫從 0 到 200px 的高度過渡時間只有 0.2s,這一點需要非常注意~

因為本來展開動畫是期望將容器的高度用 1s 的時間拉伸至 1000px,實際在 200px 的時候就停止了,所以動畫時間只有 0.2 秒。綜上,方法是好方法,但是具體使用的時候要需要具體分析。

 

最後

好了,一個小細節,希望對你有所幫助,本文到此結束,希望對你有幫助 :)

更多精彩 CSS 技術文章彙總在我的 Github -- iCSS ,持續更新,歡迎點個 star 訂閱收藏。

如果還有什麼疑問或者建議,可以多多交流,原創文章,文筆有限,才疏學淺,文中若有不正之處,萬望告知。

相關文章