題幹與適用場景
你負責一個響應式 Web 應用:點擊頭像開啟選單,選單必須跟隨頭像移動,在窄視口不能被裁切,也要支援由左至右與由右至左的書寫方向。假設顯示狀態由 Popover 或既有互動控制;本題只討論定位、換位與降級。目標職位是前端工程師,考察 CSS 佈局模型、可及性的邊界處理與漸進增強。
面試官考察點
強回答會先區分「誰控制顯示」與「誰計算幾何位置」,再用 anchor-name 建立關係,用邏輯方向的 position-area 或 anchor() 放置目標,用 position-try 處理空間不足。也要說明 Anchor Positioning 解決的是佈局耦合,不會自動取代鍵盤焦點、Popover 生命週期或瀏覽器相容策略。只背屬性名稱、宣稱所有瀏覽器都支援,都是風險訊號。
回答前需要釐清的問題
- 是否必須相容不支援 Anchor Positioning 的瀏覽器?若必須,保留普通流或 JavaScript 測量的降級路徑。
- 選單是否允許脫離錨點的捲動容器?若錨點與目標不在同一定位上下文,要檢查 containing block 與裁切邊界。
- 是否支援 RTL 與垂直書寫?若支援,優先邏輯值
block-end、inline-start,避免固定left與right。 - 選單是絕對定位還是固定定位?兩者的捲動參照物不同,會影響捲動容器與視口邊緣行為。
30 秒回答框架
「我把頭像設為 anchor,把選單設為 anchored element。先用 position-area 表達預設位置,再用 position-try 宣告空間不足時的備選位置;需要精確對齊時改用 anchor() 與邏輯 inset。顯示仍由 Popover 或元件狀態負責。上線前用 @supports 保留舊方案,並測試捲動、RTL、窄視口、縮放與鍵盤焦點。」
分步驟深入解答
先替按鈕命名,再把選單連到它:
.profile-button { anchor-name: --profile-button; }
.profile-menu {
position: absolute;
position-anchor: --profile-button;
position-area: block-end span-inline-end;
position-try: block-end span-inline-start;
}position-area 可以把錨點視為九宮格中心;block-end span-inline-end 表示選單從區塊方向末端開始,沿行方向向末端展開。position-try 讓瀏覽器在首選位置空間不足時嘗試另一側。這個規則比用視窗寬度寫多組 media query 更接近約束本身:換位原因是可用空間,而不是固定像素。
需要邊緣精確對齊時使用 anchor():
.profile-menu {
position: absolute;
position-anchor: --profile-button;
inset-inline-start: anchor(start);
inset-block-start: anchor(end);
}position-area 適合表達「放在錨點哪一格」;anchor() 適合表達「目標哪條邊對齊錨點哪條邊」。不要把兩種心智模型混成一套座標。目標可能比錨點寬,預設置中會造成視覺錯位,此時 span-inline-end 或明確 inset 更可控。
降級必須與互動狀態分離:
@supports not (anchor-name: --profile-button) {
.profile-menu { inset-inline-start: 0; inset-block-start: 100%; }
}這段降級只保證可見位置,不能假設它能處理所有溢出。若產品要求舊瀏覽器也自動換位,JavaScript 應測量 getBoundingClientRect(),選擇位置後寫入 CSS 自訂屬性,並在 resize、scroll、字型載入與選單尺寸變化時節流更新。新方案把測量與佈局交給 CSS;代價是需要驗證實作狀態與舊瀏覽器路徑。
高品質示範回答
我會先確認顯示由 Popover 或元件狀態負責,定位問題獨立處理。頭像宣告 anchor-name,選單用 position-anchor 關聯;預設用邏輯方向的 position-area 放在頭像下方,再用 position-try 宣告空間不足時向另一側展開。選單寬度與頭像不同、需要嚴格邊緣對齊時,我會改用 anchor(),不再疊加 offset。相容策略上用 @supports 提供穩定的普通定位;若舊瀏覽器也必須自動避開視口,再加入基於測量的降級。驗收會涵蓋 RTL、捲動容器、縮放、窄視口、鍵盤焦點與動態字型,確認換位沒有破壞可及性。
常見錯誤
- 錯誤表現 → 把
position-anchor當成顯示 API → 失敗原因是定位關係與互動狀態是兩層職責 → 修正方法是讓 Popover、焦點管理與 CSS 定位分別可測試。 - 錯誤表現 → 只寫
top、left卻宣稱支援 RTL → 失敗原因是實體方向不會隨書寫模式自動改變 → 修正方法是優先使用block-、inline-與邏輯position-area。 - 錯誤表現 → 用固定 media query 模擬每個邊緣 → 失敗原因是內容、縮放與捲動會改變真實可用空間 → 修正方法是用
position-try表達空間約束,舊瀏覽器再用測量降級。 - 錯誤表現 → 認為瀏覽器會替你處理焦點與螢幕閱讀器語意 → 失敗原因是 Anchor Positioning 只定義佈局 → 修正方法是獨立驗收鍵盤導覽、Escape 關閉與焦點回收。
追問及應對
追問一:選單在捲動容器內被裁切怎麼辦?
先確認目標的 containing block 與 overflow 裁切邊界。若選單必須越過容器顯示,調整定位上下文或使用固定定位,並重新驗證錨點、捲動與焦點關係;只增加 z-index 無法穿過 overflow 裁切。
追問二:同一頁有多個頭像,如何避免錨點串線?
為每個實例產生唯一的 anchor 名稱,或用作用域限制可見錨點;元件銷毀時清理關聯樣式。測試應同時開啟相鄰選單,確認每個目標只跟隨自己的錨點。
追問三:瀏覽器不支援 position-try 時如何發布?
把首選位置寫成可接受的靜態降級,使用 @supports 增強換位。若產品不能接受靜態降級,就在能力偵測後啟用測量邏輯,並把差異記錄在相容性監控中,不把未支援瀏覽器默認當成成功。