CSS 錨定定位 API 簡介

發布日期:2024 年 5 月 10 日

CSS Anchor Positioning API 是網頁開發領域的重大突破,因為它可讓您將元素定位在其他元素 (稱為「錨點」) 的相對位置。這個 API 可簡化許多介面功能的複雜版面配置需求,例如選單和子選單、工具提示、選取項目、標籤、資訊卡、設定對話方塊等等。瀏覽器內建錨定位置,可讓您建構多層式使用者介面,不必依賴第三方程式庫,進而創造出無限可能的創意體驗。

錨定位置功能自 Chrome 125 版起開放使用。

瀏覽器支援

  • Chrome:125。
  • Edge:125。
  • Firefox:不支援。
  • Safari:不支援。

資料來源

核心概念:錨點和定位元素

這個 API 的核心概念是錨點位置元素之間的關係。錨點是使用 anchor-name 屬性指定為參考點的元素。位置元素是指使用 position-anchor 屬性相對於錨點的元素,或在定位邏輯中明確使用 anchor-name

錨定元素和位置元素。

設定錨點

建立錨點很簡單。將錨點名稱屬性套用至所選元素,並指派專屬 ID。這個專屬 ID 必須在開頭加上雙連字號,就像 CSS 變數一樣。

.anchor-button {
    anchor-name: --anchor-el;
}

指派錨點名稱後,.anchor-button 就會做為錨點,可用於引導其他元素的位置。您可以透過下列任一方式,將此錨點連結至其他元素:

隱含錨點

將錨點連結至其他元素的第一種方法是使用隱含錨點,如以下程式碼範例所示。position-anchor 屬性會新增至要連結至錨點的元素,並將錨點名稱 (在本例中為 --anchor-el) 設為值。

.positioned-notice {
    position-anchor: --anchor-el;
}

使用隱含錨點關係時,您可以使用 anchor() 函式定位元素,而不需要在第一個引數中明確指定錨點名稱。

.positioned-notice {
    position-anchor: --anchor-el;
    top: anchor(bottom);
}

明確錨定

或者,您也可以直接在錨點函式 (例如 top: anchor(--anchor-el bottom) 中使用錨點名稱。這稱為明確錨點,如果您想將錨點設為多個元素,這會很方便 (請繼續閱讀,瞭解範例)。

.positioned-notice {
    top: anchor(--anchor-el bottom);
}

相對於錨點的位置元素

含有實體屬性的錨定定位圖表。

錨點定位功能建立於 CSS 絕對定位功能。如要使用定位值,您必須在已定位的元素中加入 position: absolute。接著,使用 anchor() 函式套用定位值。舉例來說,如要將錨定元素置於錨定元素的左上方,請使用下列定位方式:

.positioned-notice {
    position-anchor: --anchor-el;
    /* absolutely position the positioned element */
    position: absolute;
    /* position the right of the positioned element at the right edge of the anchor */
    right: anchor(right);
    /* position the bottom of the positioned element at the top edge of the anchor */
    bottom: anchor(top);
}
為定位元素設定邊緣位置的圖表。

現在,您有一個元素錨定在另一個元素,如下圖所示。

示範的螢幕截圖。

如要使用這些值的邏輯定位,對應方式如下:

  • top = inset-block-start
  • left= inset-inline-start
  • bottom = inset-block-end
  • right= inset-inline-end

使用 anchor-center 將定位元素置中

為了讓您更輕鬆地將錨點定位元素置中,我們新增了 anchor-center 值,可搭配 justify-selfalign-selfjustify-itemsalign-items 屬性使用。

這個範例使用 justify-self: anchor-center 將定位元素置於錨定標記上方,藉此修改上一個元素。

.positioned-notice {
  position: absolute;
  /*  Anchor reference  */
  position-anchor: --anchor-el;
  /*  Position bottom of positioned elem at top of anchor  */
  bottom: anchor(top);
  /*  Center justification to the anchor */
  justify-self: anchor-center;
}

示範的螢幕截圖。

多個錨定標記

元素可以連結至多個錨點。因此,您可能需要設定與多個錨點相關的位置值。方法是使用 anchor() 函式,並在第一個引數中明確指出要參照哪個錨點。在以下範例中,定位元素的左上角會錨定在一個錨點的右下方,而位置元素的右下角會錨定在第二個錨點的左上角:

.anchored {
  position: absolute;
  top: anchor(--one bottom);
  left: anchor(--one right);
  right: anchor(--two left);
  bottom: anchor(--two top);
}

示範的螢幕截圖。

顯示位置:inset-area

除了從絕對位置設定的預設方向位置之外,錨定 API 中還提供名為插邊區域的預設版面配置機制。

插邊區域可讓您輕鬆將定位元素 (相對於個別錨點) 放置,並適用於 9 儲存格方格,且中央有錨點元素。

各種可能的內區域定位選項,顯示於 9 儲存格的格線

如要使用內嵌區域而非絕對定位,請使用 inset-area 屬性,並搭配實體或邏輯值。例如:

  • 頂端置中:inset-area: topinset-area: block-start
  • 左側置中:inset-area: leftinset-area: inline-start
  • 正下方:inset-area: bottominset-area: block-end
  • 右側置中:inset-area: rightinset-area: inline-end

示範的螢幕截圖。

使用 anchor-size() 調整元素的大小

anchor-size() 函數也是錨點定位 API 的一部分,可用於根據錨點的大小 (寬度、高度或內嵌和區塊大小) 調整或定位錨點定位元素。

以下 CSS 範例說明如何在 calc() 函式中使用 anchor-size(height),將工具提示的高度上限設為錨定標記的兩倍。

.positioned-notice {
  position-anchor: --question-mark;

  /*  set max height of the tooltip to 2x height of the anchor  */
  max-height: calc(anchor-size(height) * 2);
}

示範的螢幕截圖。

使用錨點與頂層元素 (例如彈出式視窗和對話方塊)

錨點定位功能與 popover 等頂層元素搭配使用時,效果非常出色。和<dialog>。雖然這些元素會放置在與 DOM 子樹其他部分不同的圖層,但錨點定位可讓您將這些元素連結回去,並與不在頂層的元素一起捲動。這對分層介面來說是一大勝利。

在以下範例中,一組工具提示彈出式視窗會透過按鈕觸發開啟。按鈕是錨點,工具提示則是定位元素。您可以為已定位的元素設定樣式,方法與其他錨定元素相同。在這個具體範例中,anchor-nameposition-anchor 是按鈕和工具提示的內嵌樣式。每個錨點都需要一個不重複的錨點名稱,因此在產生動態內容時,內嵌是最簡單的方法。

示範的螢幕截圖。

使用@position-try調整錨定位置

設定初始錨點位置後,如果錨點到達所屬區塊的邊緣,您可能需要調整位置。如要建立替代的錨點位置,您可以使用 @position-try 指令和 position-try-options 屬性。

在以下範例中,選單右側會顯示子選單。選單和子選單很適合搭配使用錨定定位 API,以及彈出式屬性,因為這類選單通常會錨定在觸發條件按鈕上。

如果這個子選單的水平空間不足,您可以改為將其移至選單下方。做法是先設定初始位置:

#submenu {
  position: absolute;
  position-anchor: --submenu;

  /* initial position */
  margin-left: var(--padding);
  inset-area: right span-bottom;
}

接著,使用 @position-try 設定備用錨定位置:

/* alternate position */
@position-try --bottom {
  margin: var(--padding) 0 0 var(--padding);
  inset-area: bottom;
}

最後,請使用 position-try-options 連結這兩個元素。總結來說,這會是這樣的樣貌:

#submenu {
  position: absolute;
  position-anchor: --submenu;
  /* initial position */
  margin-left: var(--padding);
  inset-area: right span-bottom;
  */ connect with position-try options */
  position-try-options: --bottom;
}

/* alternate position */
@position-try --bottom {
  margin: var(--padding) 0 0 var(--padding);
  inset-area: bottom;
}

自動翻轉錨定位置關鍵字

如果您有基本調整 (例如從上到下或左上切換 (或兩者同時)),甚至可以略過建立自訂 @position-try 宣告的步驟,並使用瀏覽器內建支援的翻轉關鍵字 (例如 flip-blockflip-inline)。這些元素可用於取代自訂 @position-try 宣告,並可相互搭配使用:

position-try-options: flip-block, flip-inline, flip-block flip-inline;

翻轉關鍵字可以大幅簡化錨定程式碼。只要幾行程式碼,就可以建立功能完整的錨點,並設定替代位置:

#my-tooltip {
  position-anchor: --question-mark;
  inset-area: top;
  position-try-options: flip-block;
}

position-visibility 適用於子捲動器中的錨定廣告

在某些情況下,您可能需要在頁面子捲軸中固定元素。在這種情況下,您可以使用 position-visibility 控制錨點的顯示設定。錨定廣告會在何時留在檢視畫面中?何時會消失?您可以使用這項功能控制這些選項。如果您想讓位置元素停留在檢視畫面中,直到錨定標記不在檢視畫面中,請使用 position-visibility: anchors-visible

#tooltip {
  position: fixed;
  position-anchor: --anchor-top-anchor;
  position-visibility: anchors-visible;
  bottom: anchor(top);
}

或者,您也可以使用 position-visibility: no-overflow 避免錨點溢出容器。

#tooltip {
  position: absolute;
  position-anchor: --anchor-top-anchor;
  position-visibility: no-overflow;
  bottom: anchor(top);
}

功能偵測和 polyfill

由於目前瀏覽器支援的功能有限,建議您在使用這個 API 時多加留意。首先,您可以使用 @supports 功能查詢,直接在 CSS 中查看支援情形。方法是將錨點樣式包裝在以下內容中:

@supports (anchor-name: --myanchor) {

  /* Anchor styles here */

}

此外,你可以使用 CSS 錨點定位 polyfill by Oddbird,將錨定定位功能添加到作用,此功能適用於 Firefox 54、Chrome 51、Edge 79 和 Safari 10。這個 polyfill 支援大多數的基本錨點位置功能,但目前的實作方式尚未完成,且包含一些過時的語法。您可以使用 unpkg 連結,也可以直接在套件管理員中匯入。

無障礙設計注意事項

雖然錨點定位 API 可讓元素相對於其他元素定位,但它本身並不會在元素之間建立任何有意義的語意關係。如果錨定元素和定位元素之間確實存在語意關係 (例如定位元素是錨定文字的側欄註解),您可以使用 aria-details 將錨定元素指向定位元素。螢幕閱讀器軟體仍在學習如何處理 Aria 詳細資料,但支援服務已逐漸改善。

<div class="anchor" aria-details="sidebar-comment">Main content</div>
<div class="positioned" id="sidebar-comment">Sidebar content</div>
.anchor {
  anchor-name: --anchor;
}

.positioned {
  position: fixed;
  position-anchor: --anchor;
}

如果您使用錨點定位搭配 popover 屬性或 <dialog> 元素,瀏覽器會處理焦點導覽修正作業,以便提供適當的無障礙功能,因此您不需要依 DOM 順序顯示彈出式視窗或對話方塊。詳情請參閱規格中的無障礙功能注意事項。

結論

這是一項全新功能,我們很期待看到您使用這項功能建立的成果。截至目前為止,我們已看過社群相當實用的用途,例如圖表中的動態標籤、連接線、註腳,以及交叉比對視覺交叉比對。因此,試用錨定廣告位置時,請與我們分享你的寶貴意見;如果你發現任何錯誤,歡迎與我們聯絡

延伸閱讀