具代表性的面試主題

前端面試:如何用 CSS sibling-index() 和 sibling-count() 產生自適應序號?

前端中等
Offer.cc 編輯團隊發佈 更新

題幹

列表項目數量和位置會變化時,如何用 `sibling-index()` 與 `sibling-count()` 實作 CSS 版面或動畫,同時控制舊瀏覽器、Shadow DOM 和可及性行為?

題幹與適用場景

一個響應式卡片列表由 CMS 動態增刪。設計要求每張卡依兄弟總數計算寬度,並按目前位置延遲動畫,同時保留真實的可及性序號。請說明 sibling-index()sibling-count() 的語意、使用邊界、降級和驗證。

面試官考察點

  • 是否知道兩個函式回傳整數,位置從 1 開始,作用於 flat tree。
  • 是否區分 CSS 視覺順序與 DOM/輔助技術順序。
  • 是否考慮函式尚未 Baseline、@supports、靜態回退和效能。
  • 是否能說明 Shadow DOM、偽元素、隱藏節點和動態列表的影響。

回答前需要釐清的問題

  1. 目標是視覺寬度、動畫延遲,還是使用者必須讀到的序號?降級不同。
  2. 列表是否包含隱藏、模板或虛擬化節點?它們是否仍在 flat tree?
  3. 支援的瀏覽器範圍和是否允許 JavaScript 回退是什麼?
  4. 是否使用 Shadow DOM、slot 或 CSS counter?這會改變驗證方式。

30 秒回答框架

sibling-count() 回傳父級直接子元素總數,sibling-index() 回傳目前元素在兄弟中的 1-based 位置,規範按 flat tree 計算。它們適合把數量和位置用於 calc()、網格寬度或動畫延遲,但不是可靠的可及性文字來源。先用固定 CSS 回退,再以 @supports 啟用新函式;序號交給語意 HTML 或可驗證的 counter。測試動態增刪、slot、隱藏項目、瀏覽器不支援和 prefers-reduced-motion。

分步驟深入解答

1. 先確認函式回傳什麼

兩個函式都回傳整數。sibling-count() 包含元素自身;sibling-index() 從 1 計數。它們統計父元素的直接子元素,規範描述的是 flat tree,因此不能把任意後代或視覺排列順序當成兄弟位置。

2. 用於尺寸和動畫

卡片可以按兄弟數量分攤寬度,動畫延遲可以按目前位置遞增:

css
.card {
  --count: sibling-count();
  --index: sibling-index();
  flex-basis: calc(100% / var(--count));
  animation-delay: calc((var(--index) - 1) * 60ms);
}

這是視覺計算,不應取代 DOM 順序或業務編號。對空列表、單項和很大數量設定邊界,避免除零或過長延遲。

3. 處理不支援與降級

MDN 將這些函式標為 Limited availability,不能假定所有生產瀏覽器支援。先提供固定寬度或 flex 回退,再用 @supports (width: calc(100% / sibling-count())) 漸進增強。不支援時,JavaScript 只在業務確實需要動態值時更新 CSS 自訂屬性,不要讓首屏依賴腳本才能可用。

4. flat tree、slot 與隱藏節點

規範以 flat tree 定義兄弟關係;Shadow DOM 的 slot 分發會影響可見樹和測試結果。display: none、模板節點、虛擬列表佔位符是否成為直接子元素必須用實際 DOM 驗證。不要憑視覺順序推斷函式結果,也不要把 order 改變當成索引改變。

5. 可及性與語意

視覺延遲和寬度不會產生可讀序號。列表應使用 olli 或明確的 aria-posinsetaria-setsize,並確保螢幕閱讀器順序與 DOM 一致。若 CSS 只用於裝飾,停用動畫或函式不應影響內容理解。

6. 動態更新與效能

兄弟增刪會改變計算值,瀏覽器需要重新計算受影響的樣式。數千節點的列表應測量樣式重算、版面和動畫,而不是只看單一 demo。虛擬化列表可限制 DOM 數量,但此時函式只看得到視窗內兄弟,不能代表總資料集。

高品質示範回答

我會把 sibling-index()sibling-count() 當作視覺計算能力:前者回傳 flat tree 中從 1 開始的位置,後者回傳直接子元素總數。卡片寬度和動畫延遲可用它們增強,但語意序號仍由 olli 或 ARIA 提供。生產 CSS 先有固定版面回退,再用 @supports 檢測函式;對 Shadow DOM、slot、隱藏節點和虛擬化列表做真實 DOM 測試。動態增刪和大列表要測樣式重算與版面;不支援時保證內容可讀,並遵守 prefers-reduced-motion。

常見錯誤

  • 把函式當成普遍可用 → 舊瀏覽器樣式失效 → 提供固定版面和 @supports 回退。
  • 用視覺 order 推斷索引 → CSS 順序不等於 flat tree 順序 → 以 DOM 和 slot 分發測試。
  • 用 CSS 計算取代可及性序號 → 螢幕閱讀器得不到位置 → 保留 HTML 語意或 ARIA。
  • 虛擬列表直接代表總數量 → 函式只看到目前 DOM 視窗 → 由業務資料提供總數。
  • 大列表無限遞增動畫延遲 → 等待時間和重算成本失控 → 設上限並按 reduced motion 關閉。

追問及應對

sibling-count() 會把後代元素也算進去嗎?

不會。它統計父元素的直接子元素,並包含目前元素;後代節點不參與。

元素透過 slot 投影時,應按哪個順序驗證?

同時檢查 Shadow DOM 的 light tree、slot 分發後的 flat tree 和輔助技術讀取順序。用瀏覽器實際 DOM 與可及性樹驗證,不能只看原始碼排列。

舊瀏覽器完全不支援時,可以只用 JavaScript 嗎?

可以作為漸進增強,但基礎版面和內容不能依賴腳本。腳本更新 CSS 變數時還要處理增刪、SSR 首屏、停用腳本和 reduced-motion。

公開來源

同類題目