tab-header最稳妥用ul包li再套button,因button自带焦点与交互语义,ul/li提供列表语义,避免a标签跳顶或div堆砌需手动补无障碍属性。

HTML标签页导航的布局本质是「结构先行、样式约束、交互激活」,不是靠float或inline-block硬排就能稳住的;现代方案必须同时满足语义正确、键盘可操作、响应式自然、无障碍可用这四个条件。
tab-header用什么HTML标签最稳妥?
用ul包li再套button,而不是div堆砌。原因很实际:
-
button自带焦点、空格/Enter触发、禁用态语义,比a或div少写一堆tabindex和keydown监听 -
ul/li提供隐式列表语义,屏幕阅读器会读出“共3项,当前第1项”,而div堆出来的tablist需要手动补role="tablist"和aria-orientation - 避免用
a做tab按钮——href="#"会触发页面跳顶,href="javascript:void(0)"又破坏语义;真要跳转,请走路由,别假装是tab
如何让tab按钮横向排列不塌陷?
别碰float,也别依赖display: inline-block加换行符对齐。直接上display: flex:
`.tab-header {
display: flex;
flex-wrap: wrap;
}
.tab-header > li {
margin-right: 8px;
}
.tab-header > li:last-child {
margin-right: 0;
}`
关键点:
- 父容器加
flex-wrap: wrap,移动端自动折行,不用媒体查询硬切 - 子项用
margin-right而非gap,兼容IE11(虽然已不推荐,但存量项目仍存在) - 如果内容长度差异大,给
li加flex-shrink: 0防压缩,避免文字被截断
切换时内容区怎么排版才不闪、不跳?
用hidden属性控制显隐,而不是display: none内联样式:
- 在CSS里统一写
[hidden] { display: none; },所有隐藏逻辑收口到一处,JS只负责增删hidden属性 - 配合
opacity和transition做淡入淡出:激活面板先opacity: 0,再hidden移除,再opacity: 1;这样动画不会因display: none中途中断 - 每个
tabpanel必须设role="tabpanel"和aria-labelledby,指向对应tab的id;否则屏幕阅读器会把所有面板内容连读一遍
键盘导航支持不能只靠tab键
用户按Tab进入tab区域后,左右方向键必须能切换焦点,Enter/Space激活,Home/End跳首尾——这些不是锦上添花,是WCAG 2.1强制要求:
- 给
ul.tab-header加tabindex="0",确保可聚焦 - 监听
keydown时,用event.key判断ArrowLeft/ArrowRight,调用nextElementSibling.focus()移动焦点,别只改aria-selected - 按Enter时,显式触发
click()事件,复用已有点击逻辑,避免状态不同步 - 循环切换要处理边界:到末尾再按右箭头,焦点应回到第一个
tab,不是卡死或报错
最容易被忽略的是初始状态——所有tab默认无aria-selected="true",所有tabpanel都带hidden,页面加载完就是白屏。必须在DOM ready后,手动激活第一个tab并移除其hidden。这一步漏了,整个组件就不可用。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











