必须为summary元素显式定义:focus-visible样式以确保键盘用户可见焦点,因浏览器默认样式不统一且safari可能不渲染;所有聚焦逻辑仅作用于summary,details不可聚焦;图标需与文字同属一个可聚焦区域,样式须优先加载。

summary 元素的:focus-visible 样式必须显式定义
浏览器对 summary 的默认聚焦样式(通常是蓝色虚线环)在不同 UA 下差异大,且部分版本 Safari 会完全不渲染聚焦环,导致键盘用户无法感知当前焦点位置。这不是 bug,而是 UA 样式未统一覆盖该元素所致。
必须手动写 summary:focus-visible,不能只依赖 :focus——因为现代浏览器(Chrome 86+、Firefox 89+、Safari 15.4+)已普遍启用 :focus-visible 以区分鼠标/键盘触发的聚焦,避免鼠标点击后意外出现环。
- ✅ 推荐写法:
summary:focus-visible { outline: 2px solid #007aff; outline-offset: 2px; } - ❌ 避免仅写
summary:focus { outline: ... },这会让鼠标点击后也出环,干扰视觉 - ⚠️ 不要用
outline: none或outline: 0—— 这直接破坏可访问性,WCAG 2.4.7 明确要求键盘焦点必须有清晰指示 - 如果项目用 CSS 重置库(如 modern-normalize),检查是否误将
summary归入button, input, select, textarea等重置范围,需单独还原
details 标签本身不接受焦点,别给它加 focus 样式
details 元素不是可聚焦元素,其 tabindex 属性无效,:focus 或 :focus-within 在它身上不会触发。所有聚焦逻辑都落在 summary 上——这是规范强制行为,不是浏览器缺陷。
常见错误是给 details 写 details:focus { outline: ... },结果毫无反应;或试图用 details:focus-within 捕获子元素聚焦,但 summary 的聚焦不会冒泡到 details 外层(它不是容器级焦点目标)。
- ✅ 正确做法:所有聚焦样式只作用于
summary及其伪元素(如summary::before) - ✅ 若需视觉反馈延伸到折叠区,可用
details[open] summary:focus-visible加粗边框或背景色,而非操作details - ❌ 不要给
details设tabindex="0",既无效果,又可能误导屏幕阅读器
自定义图标时,:focus-visible 必须包裹整个交互区域
当用 summary::before 插入图标(如 ▶ / ▼)并配合 transform 旋转时,图标本身不参与焦点,但点击热区仍由 summary 定义。若只给文字设 focus-visible,而图标区域无响应,触屏或高缩放用户会误判可点范围。
关键点:图标和文字必须在同一块可聚焦矩形内,不能靠 position: absolute 把图标移出 summary 流式布局,否则热区断裂。
- ✅ 安全做法:用
padding-left预留图标空间,summary::before设为display: inline-block,确保整体宽度包含图标 - ✅ 聚焦样式应覆盖整个
summary行盒:summary:focus-visible { background-color: #f5f5f7; border-radius: 4px; } - ❌ 避免
summary::before { position: absolute; left: 0; }+summary { padding-left: 0; },这会让图标悬空、热区变窄 - ⚠️ iOS Safari ≤16.6 中,
summary的min-height若设得太小(如min-height: 1em),会导致聚焦环被截断,建议设为min-height: 2rem保底
键盘操作下,空格/回车触发 toggle,但 focus 样式不能延迟出现
用户按 Tab 进入 summary 后,按 Space 或 Enter 会立即切换 open 状态,此时 :focus-visible 样式必须同步存在。若 CSS 加载延迟、或 JS 动态插入样式表,可能导致焦点环“闪一下就消失”,让用户困惑是否已聚焦成功。
这不是事件顺序问题,而是样式表加载时机问题。尤其在 SSR 或微前端场景中,summary 的样式可能晚于 HTML 解析完成。
- ✅ 把
summary:focus-visible规则放在主 CSS 文件最前部,或内联到中 - ✅ 若用 CSS-in-JS(如 Emotion),确保该规则生成为
<style></style>标签且优先级高于重置规则 - ❌ 不要在
toggle事件回调里用 JS 切换 class 来模拟聚焦效果——这绕过了原生焦点管理,屏幕阅读器无法识别 - ⚠️ Chrome DevTools 的 “Emulate focus” 功能有时不触发
:focus-visible,请务必用真实键盘测试
summary 节点,也不能假设所有浏览器把图标和文字视为同一热区。稍有偏移,键盘用户就会卡在“知道这里有东西、但不知道怎么点”。前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











