CSS interpolate-size 怎麼用?讓 height: auto 動畫保留 fallback
CSS 做展開面板時,最常遇到的限制是:關閉狀態可以寫成 height: 0,開啟狀態卻需要內容決定高度,也就是 height: auto。傳統 transition 不能直接在數字和 intrinsic size 之間補間,所以面板常常只能瞬間跳開,或改用估算過的 max-height。
interpolate-size: allow-keywords 提供另一條漸進增強路徑,讓瀏覽器在長度和 auto、min-content、max-content、fit-content 等 intrinsic size 之間做過渡。不過 MDN 目前仍將它標為非 Baseline,不能假設所有瀏覽器都支援。
先看沒有這個屬性的限制
假設按鈕會替面板切換 is-open class:
.panel { height: 0; overflow: hidden; transition: height 240ms ease;}
.panel.is-open { height: auto;}在不支援 intrinsic size interpolation 的瀏覽器中,0 到 auto 沒有可計算的中間數值,因此不會得到預期的連續動畫。把 max-height 設得很大雖然看似能繞過問題,卻會帶來兩個實際麻煩:
- 面板內容較短時,動畫時間和真實高度不一致。
- 內容高度有上限時,使用者可能看不到超過上限的內容。
用 interpolate-size 讓 height: auto 可過渡
把屬性放在
:root { interpolate-size: allow-keywords;}
.panel { height: 0; overflow: hidden; transition: height 240ms ease;}
.panel.is-open { height: auto;}這個寫法的重點不是「所有高度都能動畫」,而是明確允許一端是長度、另一端是 intrinsic size。interpolate-size 預設仍是 numeric-only;沒有 allow-keywords 時,瀏覽器不會把 auto 當成可補間的目標。
如果只想讓某個元件使用,也可以把屬性縮小到元件容器:
.accordion { interpolate-size: allow-keywords;}局部套用比較容易控制影響範圍,尤其頁面同時有很多會改變尺寸的互動元件時。
需要計算時才用 calc-size()
calc-size() 適合在 intrinsic size 上再做計算,例如開啟面板時需要多留一段空間:
.panel.is-open { height: calc-size(auto, size + 1rem);}把 calc-size() 放進值裡,等同於對該選擇啟用 interpolate-size: allow-keywords。如果沒有要做計算,直接使用 interpolate-size 會比較容易讀懂,也能把「允許 intrinsic size 動畫」和「對尺寸做運算」分開。
還要注意:interpolate-size 不能讓兩個 intrinsic size 彼此互相補間;至少有一端要是 length-percentage。因此 height: max-content 到 height: auto 不能只靠這個屬性保證動畫。
用 @supports 保留無動畫 fallback
這個功能仍不是所有瀏覽器都支援,應把「內容可用」放在「動畫存在」之前:
.panel { height: 0; overflow: hidden;}
.panel.is-open { height: auto;}
@supports (interpolate-size: allow-keywords) { :root { interpolate-size: allow-keywords; }
.panel { transition: height 240ms ease; }}
@media (prefers-reduced-motion: reduce) { .panel { transition: none; }}不支援的瀏覽器會直接從 0 切到 auto,但不會因為等不到動畫而把內容留在關閉狀態。若產品需要更細緻的跨瀏覽器動態高度,可改用 JavaScript 量測實際高度;那是另一種成本與維護邊界,不要把 max-height 的估值誤當成通用解法。
動畫之外,還要處理可存取性
CSS 高度切換只處理視覺狀態,按鈕與面板之間的狀態仍要由 HTML 或 JavaScript 維護。至少確認:
- 切換按鈕的 aria-expanded 會隨開關更新。
- aria-controls 指向正確的面板 id。
- 面板關閉時,不會讓鍵盤焦點落在視覺上不可見的控制項。
- 使用 prefers-reduced-motion 時不要求使用者等待動畫。
- 若使用 hidden 屬性,先確認你的切換流程不會因為元素立刻消失而失去動畫目標。
可以先用瀏覽器的 CSS 支援檢查確認語法是否可用:
CSS.supports("interpolate-size", "allow-keywords");CSS.supports("height", "calc-size(auto, size + 1rem)");這個檢查只代表目前瀏覽器理解語法,不代表你的面板內容、overflow、focus 管理或 reduced motion 行為都已驗證。仍要以實際開啟、關閉、鍵盤操作和窄螢幕測試為準。
什麼時候不要用它
以下情境不適合直接套用:
- 元件的開關狀態由 display: none 控制,元素沒有可用的尺寸過渡階段。
- 內容高度頻繁變動,動畫期間可能持續重新排版,應先處理資料載入與 layout stability。
- 目標瀏覽器不支援,而且產品不接受無動畫 fallback。
- 需求其實是固定高度或裁切效果,使用明確的長度值會更容易驗證。
interpolate-size 適合拿來改善「內容決定尺寸」的互動,不是所有展開元件的效能開關。若元件本身還有大量畫面外內容,應另外評估 content-visibility 與預估尺寸造成的版面位移。
結論:先做可用 fallback,再加 intrinsic size 動畫
interpolate-size: allow-keywords 可以讓 height: 0 與 height: auto 之間有更自然的過渡,但目前仍要把它當成 progressive enhancement。先確保面板在不支援時仍能開啟、關閉和使用鍵盤,再透過 @supports 加上動畫;只有需要運算時才引入 calc-size()。
常見問題
Q: interpolate-size 能讓兩個 auto 或兩個 intrinsic size 互相動畫嗎?
A: 不能只靠這個屬性保證。官方定義是讓長度或百分比和 intrinsic size 之間補間,兩端都是 intrinsic size 時仍沒有可用的數值插值路徑。
Q: calc-size() 和 interpolate-size 要選哪一個?
A: 只要允許 auto 等 intrinsic size 參與動畫,使用 interpolate-size 比較直接;需要在 intrinsic size 上加減長度或做其他計算時,才使用 calc-size()。
Q: 這個 CSS 功能可以直接用在 production 嗎?
A: 先查目標瀏覽器的相容性,再用 @supports 提供無動畫 fallback。MDN 目前將 interpolate-size 標為非 Baseline,因此不能把支援狀態當成全瀏覽器一致。
參考資料:
回報錯字、失效連結,或告訴我你想看的延伸主題。