這個問題源自於掘金上的一個留言,一個朋友問到,為什麼我下面這段程式碼的高度過渡動畫失效了?
虛擬碼大概是這樣:
{ 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 的,當然,可能有兩個小缺陷,
- 如果實際場景中
max-height
需要用到並且有其它作用,那麼可能這種方法就無法滿足需求了 - 另一個缺點就是視覺上有延遲,和實際高度相差越大越明顯。也就是說,如果容器實際高度只有 200px,
max-height
為 1000px,動畫時間為 1s,緩動函式為 linear。實際動畫從 0 到 200px 的高度過渡時間只有 0.2s,這一點需要非常注意~
因為本來展開動畫是期望將容器的高度用 1s 的時間拉伸至 1000px,實際在 200px 的時候就停止了,所以動畫時間只有 0.2 秒。綜上,方法是好方法,但是具體使用的時候要需要具體分析。
最後
好了,一個小細節,希望對你有所幫助,本文到此結束,希望對你有幫助 :)
更多精彩 CSS 技術文章彙總在我的 Github -- iCSS ,持續更新,歡迎點個 star 訂閱收藏。
如果還有什麼疑問或者建議,可以多多交流,原創文章,文筆有限,才疏學淺,文中若有不正之處,萬望告知。