最直接方案是用 display 切换,但需先遍历隐藏所有面板再显示目标;hidden 属性更优,可暂停媒体资源并提升无障碍支持;:target 和 radio+checked 是纯 CSS 替代方案,需配合 ARIA 与键盘导航实现合规标签页。

用 display 切换最直接,但必须先清空再显目标
点击标签后只让对应内容区可见,其余全隐藏——这是核心逻辑。常见错误是只设 targetEl.style.display = "block",却没遍历所有面板统一设为 "none",结果多个内容同时显示,或全空白(尤其首次加载时)。
实操建议:
立即学习“前端免费学习笔记(深入)”;
- 所有内容区初始加
style="display: none;"或统一 class 如.tab-pane { display: none; } - 每个按钮加
data-tab属性,如<button data-tab="home">首页</button> - JS 中先执行
document.querySelectorAll('.tab-pane').forEach(p => p.style.display = 'none'),再查document.getElementById('panel-' + tab)并设display = 'block' - 务必检查
tab值是否存在、对应元素是否找到,否则会报Cannot set property 'display' of null
用 hidden 属性比 display: none 更稳妥
hidden 不只是视觉隐藏:它会暂停内部 <video></video>、<audio></audio>、<iframe></iframe> 的运行,自动处理焦点和可访问性状态,语义也更准确。而 display: none 只是脱离渲染流,资源可能仍在后台加载(Safari 下 <video></video> 就常继续缓冲)。
实操建议:
立即学习“前端免费学习笔记(深入)”;
- 内容区用
hidden属性初始化,如<div id="panel-home" role="tabpanel" hidden> <li>默认面板首次加载时,必须手动移除 <code>hidden,否则白屏 - 切换逻辑只需两步:
document.querySelectorAll('[role="tabpanel"]').forEach(p => p.hidden = true),再设目标p.hidden = false - 不支持 IE,需降级:CSS 中补
[hidden] { display: none !important; } - 用
:target:内容区加id,CSS 写.tab-content { display: none; } .tab-content:target { display: block; },首屏靠.tab-content:first-of-type { display: block; } - 用
radio:所有<input type="radio" name="tabs">必须同名;label必须正确绑定(for或包裹);内容区用~兄弟选择器定位,如#tab1:checked ~ #content1 { display: block; } - 两者都需注意:内容区初始必须统一设
display: none,否则首屏闪出多个 - 外层容器加
role="tablist",每个按钮加role="tab"、tabindex="0"(当前激活项设tabindex="-1") - 内容区加
role="tabpanel",并用aria-labelledby指向对应按钮的id - 监听
keydown,对ArrowLeft/ArrowRight实现横向切换 - 含
<input>的面板切走后,再切回需手动恢复焦点和滚动位置
纯 CSS 方案选 :target 还是 radio + :checked?
:target 适合静态文档页,URL 锚点可分享;radio + :checked 能做动画、有默认选中、结构可控,但无法键盘空格切换,也不支持 URL 同步。
实操建议:
立即学习“前端免费学习笔记(深入)”;
别漏掉 ARIA 和键盘导航支持
仅靠视觉切换的标签页对屏幕阅读器用户基本不可用。Tab 键进不去、方向键切不了、焦点丢失、滚动归零——这些不是边缘问题,是合规硬要求。
实操建议:
立即学习“前端免费学习笔记(深入)”;
hidden 没初始化、tabindex 没更新、或 video 在后台偷偷加载。



















