
本文介绍如何利用 CSS 的 :focus-within 伪类,在不依赖 JavaScript 的前提下,让巨型菜单(mega menu)既响应鼠标悬停,也支持键盘 Tab 导航聚焦时自动展开,提升可访问性与用户体验。
本文介绍如何利用 css 的 `:focus-within` 伪类,在不依赖 javascript 的前提下,让巨型菜单(mega menu)既响应鼠标悬停,也支持键盘 tab 导航聚焦时自动展开,提升可访问性与用户体验。
在构建符合无障碍标准(WCAG)的导航菜单时,仅靠 :hover 实现巨型菜单展开是不够的——它无法被键盘用户(如使用 Tab 键导航的视障用户或偏好键盘操作的用户)触发。原方案尝试对
解决方案是改用现代 CSS 伪类 :focus-within:它会在该元素自身或其任意后代元素获得焦点时生效,完美适配
✅ 正确实现方式(纯 CSS)
只需将原 CSS 中的 li.has-children:focus .mm-cont 替换为 li.has-children:focus-within .mm-cont:
/* 关键修改:用 :focus-within 替代 :focus */
li.has-children:hover .mm-cont,
li.has-children:focus-within .mm-cont {
display: flex;
}同时确保 HTML 结构中:
立即学习“前端免费学习笔记(深入)”;
- 保留 tabindex="1"(非必需,但有助于明确导航顺序);
- 其子 标签天然可聚焦( 默认可聚焦),无需额外设置 tabindex;
- .mm-cont 保持 display: none 初始状态,并通过上述规则动态显示。
? 完整工作示例
<input type="text" placeholder="start here" tabindex="0" />
<nav>
<ul>
<li class="has-children" tabindex="1">
<a href="#">Lorem</a>
<div class="mm-cont">
<ul class="sub-menu">
<li><a href="#">Lorem</a></li>
<li><a href="#">Ipsum</a></li>
</ul>
<ul class="sub-menu">
<li><a href="#">Dolor</a></li>
<li><a href="#">Sit</a></li>
</ul>
</div>
</li>
<li tabindex="2"><a href="#">Ipsum</a></li>
<li tabindex="3"><a href="#">Dolor</a></li>
<li tabindex="4"><a href="#">Sit</a></li>
</ul>
</nav>? 提示:tabindex 值建议使用 0(自然文档流顺序)或省略(对 和
⚠️ 注意事项与兼容性
- :focus-within 已获主流浏览器广泛支持(Chrome 60+、Firefox 52+、Safari 15.4+、Edge 79+),IE 完全不支持;若需兼容 IE,必须引入 JavaScript 回退方案。
- 确保 .mm-cont 内部链接也具备合理 tabindex 顺序,用户可通过 Tab 键继续进入子菜单项。
- 避免在 .mm-cont 上设置 display: none 之外的隐藏方式(如 visibility: hidden 或 opacity: 0),否则屏幕阅读器可能仍会读出内容;如需视觉隐藏但保留可访问性,应结合 aria-hidden="true" 与 clip-path 或 position: absolute; width: 1px; height: 1px; overflow: hidden; 等组合方案。
通过 :focus-within,我们以零 JavaScript 成本实现了鼠标与键盘双模交互的一致体验,是现代前端可访问性实践中的关键技巧之一。


















