📋 目錄
你寫過多少次這樣的程式碼:點擊按鈕後,用
getBoundingClientRect()計算按鈕位置,再用position: fixed把下拉選單放到按鈕旁邊?每次還要處理視窗 resize、scroll 時的位置更新?CSS Anchor Positioning 讓這一切成為歷史——用純 CSS,宣告式地描述「這個元素要放在那個元素旁邊」。
前言:為什麼 Anchor Positioning 這麼重要?
前端工程師做 UI 互動時,最常見的問題之一:「把 B 元素放在 A 元素的某個位置旁邊」。
這個問題看起來簡單,做起來卻處處是坑:
- 按鈕在畫面中央時,Tooltip 要顯示在按鈕上方
- 按鈕在畫面邊緣時,Tooltip 要自動翻轉到另一側,避免被裁切
- 使用者滾動頁面或 resize 視窗時,Tooltip 位置要跟著調整
- 父層有
transform: scale()時,Tooltip 的座標參照點怎麼算?
過去這些全部要靠 JavaScript 處理:監聽 scroll、resize、mousemove,計算 getBoundingClientRect(),再動態更新 CSS。效能差、程式碼複雜、還容易有 bug。
CSS Anchor Positioning 的想法:讓元素和元素之間自動建立定位關係,瀏覽器幫你處理所有座標計算。
瀏覽器支援狀態
2024 年是 CSS Anchor Positioning 的元年:
| 瀏覽器 | 支援版本 |
|---|---|
| Chrome | 125+(2024 年 5 月) |
| Firefox | 129+(2024 年 8 月) |
| Safari | 18+(2024 年 9 月,iOS 18 同時支援) |
三個主要瀏覽器全部完成支援,可以開始在生產環境使用。台灣使用者瀏覽器市佔率以 Chrome 為主, Safari 支援後市佔率障礙已消失。
核心語法:三個關鍵屬性
1. anchor-name:給元素取名字
/* 讓 .anchor-btn 成為一個錨點 */
.anchor-btn {
anchor-name: --my-button; /* 自訂名稱,--my-button 就是它的身份 */
}
anchor-name 的值是一個 custom identifier(建議用 -- 前綴,符合 CSS 變數命名慣例)。
2. position-anchor:指定參照錨點
/* 讓子元素 .tooltip 參照 --my-button 這個錨點 */
.tooltip {
position-anchor: --my-button;
/* 從此 .tooltip 的定位計算都以 .anchor-btn 為準 */
}
3. anchor() 函式:取得錨點位置
.tooltip {
position: absolute;
/* 把自己放在錨點的右側 */
left: anchor(--my-button right);
/* 垂直置中於錨點 */
top: anchor(--my-button center);
}
anchor() 接受兩個參數:錨點名稱、和要對齊的邊。
實際應用:Tooltip
HTML 結構
<button class="anchor-btn" aria-describedby="tooltip-1">
點我
</button>
<div id="tooltip-1" class="tooltip" role="tooltip">
這是一個提示框
</div>
CSS 實作
/* 第一步:設定錨點 */
.anchor-btn {
anchor-name: --my-button;
}
/* 第二步:Tooltip 參照這個錨點 */
.tooltip {
position-anchor: --my-button;
/* 定位:絕對定位,位於錨點右側 */
position: absolute;
left: anchor(--my-button right); /* 左邊對齊錨點的右邊 */
bottom: anchor(--my-button top); /* 底部對齊錨點的頂部(自然形成上方顯示) */
/* 視覺 */
background: #1a1a2e;
color: #fff;
padding: 0.5rem 0.75rem;
border-radius: 6px;
font-size: 0.875rem;
white-space: nowrap;
/* 預設隱藏 */
display: none;
}
/* 滑鼠懸停時顯示 */
.anchor-btn:hover + .tooltip {
display: block;
}
這段 CSS 實現了:當按鈕在任何位置(畫面中央、邊緣、會被裁切的地方),Tooltip 都會正確顯示在按鈕上方——不需要任何 JavaScript。
anchor-size():根據錨點尺寸調整
如果 Tooltip 寬度要跟随錨點的寬度呢?
.tooltip {
position: absolute;
/* 寬度與錨點相同 */
width: anchor-size(--my-button width);
/* 最小寬度 */
min-width: anchor-size(--my-button min-width);
/* 高度 */
height: anchor-size(--my-button height);
}
自動翻轉:inset-area
Anchor Positioning 最強大的功能:inset-area 讓你宣告「優選這個位置,但視情況自動翻轉」。
.tooltip {
position: absolute;
/* 優先顯示在錨點上方,如果空間不夠,自動換到下方 */
position-anchor: --my-button;
inset-area: top span-right;
}
inset-area: top span-right 的意思是:
- 第一選項:錨點上方,
span-right表示水平佔滿錨點寬度(向右延伸) - 如果上方空間不夠:瀏覽器自動翻轉到「錨點下方」
過去要寫幾十行 JavaScript 才能實現的「智慧翻轉」,現在一行 CSS 就搞定了。
inset-area 的可用區域
/* 九宮格 + 四邊: */
inset-area: top; /* 錨點正上方 */
inset-area: bottom; /* 錨點正下方 */
inset-area: left; /* 錨點正左方 */
inset-area: right; /* 錨點正右方 */
inset-area: top left; /* 錨點左上方 */
inset-area: top span-right; /* 錨點上方,寬度向右延伸 */
inset-area: bottom span-all; /* 錨點下方,充滿整個錨點寬度 */
與 Popover API 結合
CSS Anchor Positioning 特別適合與 Popover API 搭配使用:
<button class="anchor-btn" popovertarget="my-popover">
開啟 Popover
</button>
<div id="my-popover" popover class="popover-panel">
這個 Popover 會自動對齊到按鈕
</div>
.anchor-btn {
anchor-name: --trigger;
}
.popover-panel {
position-anchor: --trigger;
/* 自動出現在錨點下方 */
position: absolute;
inset-area: bottom span-right;
/* Popover 本身的樣式 */
margin: 0;
padding: 1rem;
border-radius: 8px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
}
popover 屬性讓元素成為 Popover,具備:
- 點擊外部自動關閉
- 無障礙的 focus trap
::backdrop偽元素支援
Anchor Positioning 負責定位,Popover API 負責互動邏輯,兩者結合是 2025 年做 Tooltip/Dropdown 的最佳實踐。
與 JavaScript 定位的效能比較
| 項目 | JavaScript 定位 | CSS Anchor Positioning |
|---|---|---|
| 程式碼量 | 50-100 行 | 10-15 行 |
| scroll 監聽 | 需要 | 不需要(瀏覽器原生處理) |
| resize 監聽 | 需要 | 不需要 |
| 翻轉邏輯 | 手動實作 | 瀏覽器原生支援 |
| 效能 | JS 執行緒負擔 | 瀏覽器合成執行,幾乎無成本 |
| transform 影響 | 需要處理 | 瀏覽器自動處理 |
限制與 Fallback
巢狀錨點
Anchor Positioning 目前不支援跨 Shadow DOM(例如 Web Component 內部的元素無法作為外層的錨點)。這是已知的限制,未來版本可能會改善。
Fallback 策略
在还不支援的瀏覽器(幾乎沒有了)提供 JavaScript fallback:
@supports (anchor-name: --foo) {
/* 支援時用 CSS */
.tooltip {
position-anchor: --my-button;
inset-area: top;
}
}
@supports not (anchor-name: --foo) {
/* 不支援時用 JavaScript 定位(已沒有這種瀏覽器) */
}
實際上 2026 年初,所有主流瀏覽器都已支援,可以不用寫 @supports fallback。
常見問題
Q:Anchor Positioning 和 position: fixed + transform 的做法有什麼不同?
A:position: fixed 是相對於 viewport 定位,不受父層影響。Anchor Positioning 是相對於另一個 DOM 元素定位,會跟隨那個元素的位置變化。兩者是互補的——當你需要「跟著某個元素移動」時,Anchor 是正確的選擇。
Q:可以多個元素參照同一個錨點嗎?
A:可以。多個元素可以 position-anchor: --my-button 參照同一個錨點,適用於一個按鈕觸發多個附屬面板的場景。
Q:Anchor Positioning 可以用在 Grid 或 Flex 裡嗎?
A:可以。Anchor Positioning 和 position: absolute 相容,可以用在你已經存在的任何佈局系統上,不會破壞現有的排版。
Q:有範本庫推薦嗎?
A:Chrome 團隊推出了 Gold Standard 測試範本(Anchor Positioning Gold Standard),包含各種常見 UI 模式的參考實作,可以直接拿來改。
總結:CSS 定位的未來
CSS Anchor Positioning 的核心價值:把「元素跟隨另一個元素」這件事,從 JavaScript 移到 CSS,效能更好、程式碼更少、語意更清楚。
這篇文章涵蓋:
- Anchor Positioning 的背景與瀏覽器支援(2024 年三大瀏覽器全部完成支援)
- 三個核心語法:
anchor-name、position-anchor、anchor() anchor-size()根據錨點尺寸調整inset-area的自動翻轉邏輯- 與 Popover API 結合的最佳實踐
- 效能比較與瀏覽器支援狀態
下一步:在你的專案找一個有用到 JavaScript 定位的 Tooltip 或 Dropdown,用 CSS Anchor Positioning 替換掉。體驗「刪掉 JS 定位邏輯後,功能照樣正常運作」的快感。
想了解 CSS 的其他新功能,可參考 《CSS Container Queries 完全指南:回應式元件的下一個時代》。