建立永久應用程式導覽

網頁功能: 彈出式視窗 錨定位置

新手上路導覽需要疊加層,在使用者與醒目顯示的功能互動時,疊加層會持續顯示。與自動彈出式視窗不同,手動彈出式視窗不會在使用者點選頁面其他位置時關閉。結合 popover="manual" 和 CSS 錨定定位,即可建立非模態的繫結導覽步驟。

HTML

<div id="feature-target">Highlight this feature</div>

<!-- MANDATORY: Enforce overlay dialog semantics and accessible name bindings -->
<div id="tour-step" popover="manual" role="dialog" aria-labelledby="tour-title">
  <!-- Assume an <h1> precedes this element in the full document outline -->
  <h2 id="tour-title">Step 1</h2>
  <p>Learn how to use this feature.</p>
  <button popovertarget="tour-step" popovertargetaction="hide">Got it</button>
</div>

CSS

#feature-target {
  anchor-name: --feature-target;
}

#tour-step {
  popover: manual;
  position-anchor: --feature-target;
  position-area: right center;
  inset: auto;
  margin: 1rem;
  padding: 1rem;
  border: 1px solid blue;
  border-radius: 0.5rem;
  background: aliceblue;
}

JavaScript

const tourStep = document.getElementById('tour-step');
tourStep.showPopover();
// MANDATORY: Programmatically route focus into the non-modal popover so keyboard/assistive technology users immediately perceive the new context
tourStep.querySelector('button').focus();

導入指南

  • 必要:使用 popover="manual",防止導覽步驟在使用者互動期間意外關閉。
  • 必要:使用 role="dialog" 標記容器,並透過 aria-labelledby 連結其標題。
  • 必要:開啟彈出式視窗後,立即將焦點移至視窗內,避免焦點遺失。
  • 建議使用 CSS 錨定定位,將導覽步驟與要說明的特定功能連結。
  • 務必在彈出式視窗中提供明確的「關閉」或「下一步」按鈕,並使用 popovertargetaction="hide"。

備用策略

Popover 的備用方案和瀏覽器支援

Popover API 主要是漸進增強,但其定義行為 (頂層升級、輕觸關閉和 popovertarget 叫用) 沒有僅限 CSS 的對等項目。舊版瀏覽器需要 polyfill,如果不想提供,則需要手動備用方案。

Polyfill:如要在舊版瀏覽器中支援 popover 屬性,請視情況載入 @oddbird/popover-polyfill。必要:檢查 HTMLElement.prototype 上的 popover 屬性,偵測功能,並僅在缺少原生支援時載入 polyfill,請勿無條件載入。

使用套件組合器或匯入對應:

// MANDATORY: Feature detect 'popover' on HTMLElement.prototype.
if (!("popover" in HTMLElement.prototype)) {
  import("@oddbird/popover-polyfill");
}

如果沒有繫結器,請從 <script type="module"> 內的 CDN 匯入:

<script type="module">
  if (!("popover" in HTMLElement.prototype)) {
    import("https://unpkg.com/@oddbird/popover-polyfill@latest/dist/popover.min.js");
  }
</script>

樣式注意事項:Polyfill 無法定義實際的 :popover-open 虛擬類別,因此會改為套用 .\:popover-open 類別。必要:請使用 :is() 或 :where() 結合兩者,否則不支援 :popover-open 的瀏覽器會捨棄整個規則:

[popover]:is(:popover-open, .\:popover-open) {
  display: block;
}

或者,如要使用不含 polyfill 的舊版備用方案,請使用 position: fixed,並透過 getBoundingClientRect() 手動計算座標,或在用途允許的情況下,使用 inset: auto 預設定位。

anchor-positioning

如要支援不支援錨定定位的瀏覽器,可以選擇使用 polyfill 或純 CSS 備用方案。

選項 1:Polyfill 備用方案

@oddbird/css-anchor-positioning polyfill 可用於模擬錨定位置。這項功能不支援隱含錨定標記,因此您「必須」在觸發條件中加入明確的錨定標記名稱。此外,polyfill 不支援彈出式視窗上的 position-area,因此您必須在所需插邊上使用 anchor(),而非 position-area。

<script type="module">
  if (!CSS.supports('anchor-name: --foo')) {
    await import("https://unpkg.com/@oddbird/css-anchor-positioning");
  }
</script>
#tour-step {
  /* If using the anchor positioning polyfill with a popover, DO use `anchor()` functions instead of `position-area`. */
  left: anchor(right);
  top: anchor(top);
}
選項 2:非 Polyfill CSS 備用方案

如果不想使用 polyfill,可以使用 @supports not,將工具提示預設為可視區域底部的固定位置。

@supports not (anchor-name: --foo) {
  #tour-step {
    position: fixed;
    bottom: 0;
    left: 0;
    right: 0;
    width: 100%;
    margin: 0;
    border-radius: 0;
  }
}