返回知识中心
平台

Popover API:焦点、轻量关闭与无障碍回退

围绕 popover=auto 或 manual 定义 top layer、Escape、外部点击、焦点、事件和可用回退的无障碍契约。

BotBrowser Team

文档中心

想直接进入 平台 文档吗?

这篇文章属于知识中心的指南库。若你要步骤化配置、参考说明和持续更新,请直接进入对应 docs 分区。

BotBrowser 支持重放获授权的 fixture,记录打开、关闭和焦点的可见结果;但不能保证辅助技术行为,也不会把回退实现变成浏览器的已发布支持。涉及指针与键盘的流程,还应结合指针事件无障碍检查和浏览器自动化无障碍测试。

TL;DR

  • popover="auto" 适合可轻量关闭的非模态表面;manual 适合由应用拥有每个关闭决定的表面。
  • top layer 不会自动创建焦点陷阱、无障碍名称或对话框语义。
  • 把 Escape、外部点击、焦点返回和背景 inert 作为独立结果测试。
  • beforetoggle 可以取消转换;toggle 报告已提交的状态,回退也要保留同一结果。

内容导航

触发器在 top layer 中打开 auto 或 manual popover;Escape 或外部点击关闭它并返回焦点。

选择状态模型

WHATWG HTML 规范定义 popover 属性和显示、隐藏算法。popover="auto" 适合菜单、提示和过滤器等非模态表面;浏览器会管理自动 popover 栈。popover="manual" 把关闭决定留给应用,适合多个相关表面需要同时存在或由“完成”按钮结束的流程。

不要把该属性当作 <dialog> 的同义词。Popover 不会自动成为模态,不会自动捕获焦点,也不会自动获得无障碍名称。使用真正的 button、popovertarget 和描述内容的名称。只有在确实实现菜单键盘行为时才添加菜单角色。

MDN Popover API 指南介绍 showPopover()、hidePopover() 和 togglePopover()。选择命令式路径前先做特性检测,并让界面说明内容、关闭方式以及背后仍可用的任务。

Top layer 与轻量关闭

显示后,popover 会进入 top layer。auto 提供浏览器管理的轻量关闭,但不保证在缩小视觉 viewport、缩放、虚拟键盘或 iframe 中仍有合适位置。分别测试 Escape 和外部点击。manual 必须有关闭按钮和明确的事件路径;不要使用透明覆盖层吞掉点击却让页面在语义上保持可用。

Chrome 的 Popover API 介绍说明这些目标,但不是所有浏览器、嵌入式 WebView 或辅助技术行为完全相同的证明。记录版本和 viewport,断言可见结果,不要断言具体绘制顺序。

焦点和 inert 是不同契约

显示 popover 不会决定焦点去哪里。根据它是建议、菜单还是编辑器,可以保留触发器焦点,或移动到第一个有意义的控件。保存打开者,把焦点返回仍连接且可用的元素;若打开者消失,使用约定的标题或下一步控件。不要对已脱离 DOM 的节点调用 focus()。

检查键盘、指针和辅助技术是否都能到达预期控件。manual 可以有意让背景保持可用;真正的模态任务更适合 <dialog> 与 showModal()。WCAG 键盘指南和focus-visible 指南要求检查名称、角色、状态、焦点指示器和下一步操作。

观察 beforetoggle 与 toggle

beforetoggle 在转换前触发,可以拒绝转换或准备焦点决定。toggle 在状态提交后触发。快速转换可能合并;记录 opened 或 closed-by-escape 这样的有界状态,不要保存页面文本或每次点击的审计。

const trigger = document.querySelector('#filters-button');
const panel = document.querySelector('#filters-panel');
let opener = null;

trigger.addEventListener('click', () => {
  opener = document.activeElement;
  panel.togglePopover();
});
panel.addEventListener('beforetoggle', event => {
  if (event.newState === 'open' && !trigger.isConnected) event.preventDefault();
});
panel.addEventListener('toggle', event => {
  if (event.newState === 'closed' && opener?.isConnected) opener.focus();
});

这是协调模式,不是每个浏览器事件时序相同的承诺。取消后表面和焦点仍要可用;没有事件 API 时,回退也应产生等价的应用状态。

构建可用回退

先检测 API,再使用普通按钮、初始隐藏区域和带 aria-controls 的关闭按钮。保留相同内容与焦点顺序。若任务本来是模态,应采用受支持的对话框模式,不要把 manual 假装成模态。处理方法缺失、焦点操作被拒绝、打开者被删除和 viewport 改变。BotBrowser 可以在获授权的上下文比较声明的可见状态,但不能认证读屏器播报或每个 build 的原生 top layer。

运行有界交互矩阵

路径预期结果需要调查的失败
键盘调用,auto打开,焦点可见,Escape 关闭焦点消失
外部点击,auto只关闭一次并返回焦点重复清理
关闭按钮,manual应用隐藏表面并恢复打开者没有关闭所有者
API 不可用内容和键盘路径等价回退不可达
viewport 变窄关闭出口可见且文字可读唯一出口被裁切

在缩放、减少动效、触控和窄 viewport 下重复这些行。检查 document.activeElement、无障碍名称、焦点指示器和每次关闭后的下一步。fixture 保持合成,只记录解释失败所需的状态标签。

如果 popover 还需要跟随移动的 trigger,请阅读 CSS anchor positioning 边界指南,把 anchor-name、fallback 候选和 clipping 与焦点责任分开测试。

实践结论

根据关闭所有者选择 auto 或 manual,再分别测试 top layer、轻量关闭、Escape、焦点、inert 和回退。WHATWG、MDN 与 Chrome 说明平台;BotBrowser 可重复获授权的可见 fixture,语义和无障碍恢复仍由应用负责。

来源

FAQ

popover="auto" 是模态对话框吗?

不是。需要模态语义时使用 <dialog> 和 showModal()。

top layer 会自动移动焦点吗?

不会。明确焦点目的地、返回位置以及打开者消失时的回退。

每个 popover 都应该外部点击关闭吗?

不应该。auto 提供轻量关闭;manual 把决定交给代码。关闭操作必须可发现。

#Popover API#无障碍#焦点#Top Layer#Web Platform

本文属于指南: Web 平台能力面:一致性复核地图

让 BotBrowser 从研究走向生产

先用这些指南理解模型,再进入跨平台验证、隔离上下文和面向规模化的浏览器部署。