如何仅用CSS实现通过Tab键展开Mega Menu?
不用JS实现可访问的Mega菜单:解决Tab导航不触发的问题
问题出在:你给 <li> 加了 tabindex 但Tab键切换时,焦点会优先落在内部的 <a> 标签上(因为 <a> 是默认可聚焦元素),导致 li:focus 状态根本触发不了。不过不用JS也能解决,用CSS的 :focus-within 伪类就行。
具体修改:
1. 替换CSS触发规则
把原来的hover和focus触发代码:
li.has-children:hover .mm-cont, li.has-children:focus .mm-cont { display:flex; }
改成:
li.has-children:hover .mm-cont, li.has-children:focus-within .mm-cont { display:flex; }
2. 优化Tab导航设置(可选)
可以直接删掉 <li> 上的 tabindex,因为内部的 <a> 本来就能被Tab键选中,没必要给父级li加焦点。如果要调整导航顺序,直接给 <a> 设 tabindex 更合理。
修改后的完整代码:
CSS
nav { background:#ccc; position:relative; } nav > ul { display:flex; column-gap:1.5rem; width:100%; list-style:none; margin:0; padding:0; } nav li { padding:1.5rem; } nav li a { position:relative; } nav li.has-children > a:after { content:""; display:block; width:25px; height:25px; background-image:url('https://upload.wikimedia.org/wikipedia/commons/9/9a/Caret_down_font_awesome.svg'); position:absolute; right:-30px; top:50%; transform:translateY(-50%); } .mm-cont { display:none; position:absolute; width:100%; background:#aaa; bottom:-132px; left:0; } .sub-menu { list-style:none; padding:0; } /* 鼠标悬停或子元素获焦时显示菜单 */ li.has-children:hover .mm-cont, li.has-children:focus-within .mm-cont { display:flex; }
HTML
<input type="text" placeholder="start here" tabindex="0" /> <nav> <ul> <li class="has-children"> <a href="#" tabindex="1">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><a href="#" tabindex="2">Ipsum</a></li> <li><a href="#" tabindex="3">Dolor</a></li> <li><a href="#" tabindex="4">Sit</a></li> </ul> </nav>
为什么这个方案可行?
:focus-within 会在元素本身或者它的任意子元素获得焦点时触发样式。当用户按Tab键切换到父li里的a标签时,父li会触发:focus-within,自然就展开了mega菜单。同时保留:hover规则,鼠标悬停的交互也正常,全程不用写一行JS,还符合键盘导航的可访问性要求。
内容的提问来源于stack exchange,提问作者user19103974
相关产品推荐
相关产品推荐

