应避免在内嵌套role="tablist",因其违反ARIA规范导致可访问性失效;正确做法是将tablist置于details外层或改用自定义手风琴组件,并严格管理aria-hidden、tabindex、aria-selected及状态持久化。

details 里嵌套 tablist 会破坏语义和键盘导航
原生 根本原因在于 ARIA 规范要求 常见错误是 JS 查找目标面板时用 实操要点: 只改 推荐做法(每次切换后执行): 示例片段: 用户可能在折叠前已切换到第 3 个标签页,但点击父级 解决方式不是靠 CSS 或 HTML 属性,而是用 JS 持久化记录: 这个细节常被忽略——视觉上“收起再展开”似乎只是高度变化,但语义状态其实断开了。 已自带折叠逻辑和可访问性支持,但它的内容区不是 role="tablist" 的合法容器。若强行在 后塞 ArrowLeft/ArrowRight 切换失效。tablist 必须是“顶级导航容器”,不能嵌套在交互式元素(如 )内部——否则其子项的 role="tab" 会被降级为普通按钮。
菜单
tablist 放在 外层,用 JS 控制整个 的展开状态与当前激活页签解耦,改用 aria-expanded 和 aria-controls
用 data-target 关联子标签页时,ID 匹配必须严格一致
document.getElementById(),但 HTML 中 id 值含空格、中文或以数字开头,导致匹配失败,控制台报 TypeError: Cannot read property 'classList' of null。data-target 的值必须和对应面板的 id 完全相同(区分大小写、不带 #):data-target="faq-1" → id="1-panel" 非法),建议统一用 id="panel-faq-1"
id,JS 只能操作第一个切换子标签页时,要同步更新 aria-hidden 和 tabindex
display 或 max-height 不够。若不手动设置 aria-hidden="true" 和 tabindex="-1",隐藏面板仍会被屏幕阅读器读出,键盘用户也能 Tab 进去,造成逻辑混乱。
aria-hidden,设 tabindex="0"
aria-hidden="true",设 tabindex="-1"
role="tab" 元素中,当前激活项加 aria-selected="true",其余设 "false"
const panel = document.getElementById(targetId);<br>panel.removeAttribute('aria-hidden');<br>panel.setAttribute('tabindex', '0');
折叠菜单收起时,正在显示的子标签页状态容易丢失
收起后,再展开时默认回到第 1 个——因为原生 不保存子状态。
toggle 事件,在 收起前,把当前激活页签的 data-tab-id 存进 localStorage 或组件级变量click,或直接调用切换函数sessionStorage,它在页面刷新后清空;若需跨会话保留,才用 localStorage
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











