新手入门导览需要使用叠加层,这些叠加层会在用户与突出显示的功能互动时持续显示。与自动弹出式窗口不同,手动弹出式窗口不会在用户点击页面上的其他位置时关闭。将 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,则需要手动后备方案。
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;
}
}