使用原始大小計算

網頁功能: calc-size() interpolate-size

calc-size() 是 CSS 函式,用於對 auto、min-content 和 fit-content 等內建大小關鍵字執行數學運算。必要:只有在需要透過計算或限制修改內建大小時,才使用 calc-size();如果是簡單的關鍵字動畫 (例如 0 到 auto),則必須使用 interpolate-size: allow-keywords。

導入步驟

  1. 找出內建基準:判斷應以哪個內建關鍵字 (auto、min-content 等) 做為計算基準。
  2. 定義限制:在第二個引數中使用 clamp()、min() 或 max() 等 CSS 數學函式,對內建大小強制執行設計限制。
  3. 強制:提供備用方案:請務必在使用 calc-size() 的屬性之前,立即宣告標準大小關鍵字或長度,確保版面配置在不支援的瀏覽器中仍能正常運作。
  4. 套用邏輯屬性:預設使用 inline-size 或 block-size 等邏輯屬性,確保計算結果符合文件的書寫模式。
  5. 選用:漸進增強:將複雜的版面配置邏輯或動畫包裝在 @supports (inline-size: calc-size(auto, size + 0px)) 區塊中,只向支援的瀏覽器提供進階功能。

基本語法

/* calc-size(<calc-size-basis>, <calc-sum>) — mathematical operations on intrinsic sizing keywords */
.element {
  /* MANDATORY: Always provide a fallback for browsers that do not support calc-size() */
  inline-size: min-content;
  
  /* DO: Use calc-size to modify an intrinsic basis with a calculation or function */
  inline-size: calc-size(min-content, size + 2rem);
}

有效的基準引數 (<calc-size-basis>)

第一個引數定義計算的「基本」大小。

標準關鍵字:

  • auto:元素的預設大小。
  • min-content:元素在不溢出的情況下可採用的最小尺寸。
  • max-content:元素容納一行所有內容所需的大小。
  • fit-content:等同於 clamp(min-content, auto, max-content)。
  • content:只有在 flex-basis 屬性中使用 calc-size() 時才有效。

特殊引數:

  • any:在特定內建類型不明或巢狀計算時,使用的一般基礎。
  • 巢狀 calc-size():允許進行多步驟或條件式計算。
  • <calc-sum>:特定長度、百分比或數學運算式 (例如 100px 或 20%)。以固定值做為基準時,您仍可使用 size 關鍵字 (但僅限於第二個引數),代表該基準的解析值。

強制:size 關鍵字在第一個引數 (<calc-size-basis>) 中無效。這是一個區域變數,僅用於從第二個引數 (<calc-sum>) 內參照回基礎。

有效的計算引數 (<calc-sum>)

第二個引數是數學運算式。

  • 通常會使用 size 關鍵字來參照基準值。
  • 雖然 size 關鍵字並非必要,但如果省略,計算結果會解析為固定值,完全忽略基準。
  • 可包含標準數學運算子 (+、-、*、/)。
  • 可包含 clamp()、min()、max() 和 round() 等 CSS 數學函式。
  • 必要:calc-size() 每次計算只能使用「一個」內建大小值 (基準)。您無法在同一個 calc-size() 呼叫中混合使用內建大小關鍵字。

應用實例

在原始大小之間加上動畫效果

根據預設,瀏覽器無法在長度 (例如 0px) 和內建關鍵字 (例如 auto) 之間插補。將關鍵字包裝在 calc-size() 中,即可將其設為可插補的值。

選擇合適的動畫工具

  • 強制:使用 interpolate-size: allow-keywords:用於在不進行任何數學修改的情況下,對內建大小 (例如 height: 0 到 height: auto) 進行簡單的動畫。這是簡單關鍵字內插的必要方法,理想情況下應透過 :root 全域套用。

    :root {
      /* Best practice: Enable keyword interpolation globally */
      interpolate-size: allow-keywords;
    }
    
    .item {
      height: 0;
      transition: height 0.3s ease;
    }
    
    .item.open {
      /* Simple interpolation from 0 to auto now works without calc-size() */
      height: auto;
    }
    
  • 使用 calc-size():僅限需要在轉換期間對內建大小執行數學運算 (例如新增邊框間距或限制大小) 時。

.accordion-content {
  display: block;
  overflow: hidden;
  /* MANDATORY: Fallback value for closed state */
  block-size: 0;
  transition: block-size 0.3s ease-out;
}

.accordion-content.open {
  /* MANDATORY: Fallback value for open state */
  block-size: auto;

  /* 
    DO: Use calc-size(auto, ...) to enable animation from 0 to the element's 
    intrinsic size while doing a calculation (in this case, adding a space of 2rem).
  */
  block-size: calc-size(auto, size + 2rem);
}

MANDATORY: Interpolation between two intrinsic sizing keywords is not possible directly. 轉場效果的一端必須是長度或百分比。

尊重使用者動作偏好設定

如果動畫會改變大型版面配置區域的大小,可能會對前庭障礙使用者造成特別嚴重的干擾。必要:請務必使用 prefers-reduced-motion 媒體查詢,簡化或盡量減少非必要的動畫,尊重使用者的動作偏好設定。常見策略包括完全停用動作、縮短持續時間,或將版面配置位移替換為細微的不透明度轉場效果。

.accordion-content {
  opacity: 0;
  transition: block-size 0.3s ease, opacity 0.3s ease;
}

.accordion-content.open {
  opacity: 1;
}

@media (prefers-reduced-motion: reduce) {
  .accordion-content {
    /* 
       EXAMPLE: Replacing disruptive layout animations with a subtle fade-in.
       Setting the block-size instantly and transitioning opacity 
       provides a clear state change without large-scale motion.
    */
    transition: opacity 1.5s ease;
  }

  .accordion-content.open {
    /* Jump the size instantly */
    block-size: auto;
  }
}

對內建大小套用限制

您可以將 calc-size() 與任何 CSS 數學函式 (例如 min()、max()、clamp() 或 round()) 搭配使用,確保元素的固有大小不超出設計邊界。

.dynamic-container {
  /* MANDATORY: Always provide a fallback for browsers that do not support calc-size() */
  inline-size: fit-content;

  /* 
    DO: Establish a dynamic size based on content, while:
    1. Enforcing boundaries using CSS math functions (min, clamp, etc.)
    2. Modifying the intrinsic size with fixed or relative offsets
  */
  inline-size: calc-size(fit-content, min(size + var(--extra-space), var(--max-allowed)));
}

重要考量

  • 百分比陷阱:<calc-sum> 內的百分比是根據容器大小解析,而非 size 關鍵字。舉例來說,calc-size(auto, size + 10%) 會將父項寬度的 10% 加到元素的 auto 寬度,這可能會導致非預期的結果或溢位。
  • 計算規定:強制:請使用 interpolate-size: allow-keywords,而非 calc-size() 處理簡單動畫 (例如 0 至 auto)。只有在版面配置需要對內建基準進行動態數學調整時,才應使用 calc-size()。
  • 效能注意事項:為 inline-size 或 block-size 等盒模型屬性加上動畫效果,會觸發版面配置重新計算,這可能會耗費大量資源。calc-size() 動畫主要用於版面配置關鍵元素,且非版面配置替代方案不足的情況。

備用策略

calc-size() 和 interpolate-size 是漸進增強。在不支援這些屬性的瀏覽器中,系統會忽略這些屬性,版面配置仍可正常運作,但內建關鍵字的動畫會跳轉,而非轉場。請務必提供標準關鍵字或長度做為備用。

.element {
  /* Fallback for browsers that don't support calc-size() */
  inline-size: fit-content; 
  /* Modern browsers will override the fallback */
  inline-size: calc-size(fit-content, size + 2rem);
}

動畫和轉場效果備用方案

在不支援 calc-size() 或 interpolate-size 的瀏覽器中,涉及內建大小關鍵字的轉場效果將無法插補。

  • 優雅降級:預設備用方案是狀態之間的「即時跳轉」(例如從 0 到 auto)。這通常可以接受,因為版面配置仍可正常運作。
  • 強化體驗:使用 @supports 套用複雜的版面配置邏輯或額外樣式,只有在能流暢呈現內建動畫時,這類效果才有意義。
  • 避免使用 JS 測量:雖然您可以使用 JavaScript 測量元素,並手動為其尺寸加上動畫效果,但這通常不必要,且可能導致版面配置抖動。建議現代網頁應用程式採用原生「即時跳轉」做為備用方案。

如果是動畫,備用體驗會立即跳至最終大小。如要偵測 CSS 或 JavaScript 的支援情形,請按照下列步驟操作:

/* CSS Feature Detection */
@supports (inline-size: calc-size(auto, size + 0px)) {
  .element {
    /* Apply advanced logic only when supported */
  }
}
/* JavaScript Feature Detection */
if (CSS.supports('inline-size', 'calc-size(auto, size + 0px)')) {
  // Apply advanced sizing or animations
}