最轻量零js方案是用:target伪类实现锚点标签页,需为目标元素设id并写.tab-content:target规则,首屏显示靠:first-of-type,但高亮和动画受限;radio方案更可控但结构重;hover方案仅适用演示。

用 :target 伪类实现锚点式标签页
这是最轻量、零 JS、URL 可分享的方案,适合博客归档、文档页面等静态内容。核心是让每个标签对应一个 URL 片段(如 #python),点击后浏览器自动滚动并触发 :target 样式。
常见错误现象:点击标签没反应,或内容不显示 —— 多半是没给目标元素设 id,或 CSS 中漏写了 .tab-content:target 规则。
-
.tab-content必须设display: none,否则所有内容默认堆叠显示 - 默认显示第一个标签页,靠
.tab-content:first-of-type { display: block; }实现,但要注意它会被:target覆盖(即 URL 带锚点时以 :target 为准) - 标签高亮不能直接用
a:target,因为 :target 匹配的是目标元素,不是链接本身;可把<a></a>和<section></section>合并在同一容器里,或改用 JS 补充 - 不支持过渡动画,
opacity或transform在:target下无效,这是浏览器限制
用 <input type="radio"> + :checked 实现无 JS 切换
比 :target 更可控,能做视觉反馈、支持默认选中、可加 transition 动画,但结构略重,且无法监听切换事件。
使用场景:产品介绍页、FAQ 折叠区、内部文档导航等不需要动态加载的静态模块。
- 必须隐藏
<input>,用display: none或position: absolute; clip: rect(0 0 0 0),否则会占用布局空间 - label 必须紧跟在对应 radio 后面,才能用
input:checked + label控制样式;内容区要用~(通用兄弟选择器)定位,如#tab1:checked ~ #content1 - 所有内容区初始状态必须统一设为
display: none,否则首屏可能闪出多个面板 - radio 的
name属性必须一致,否则无法互斥;checked属性只加在一个上,作为默认项
用 :hover 实现悬停式标签页(仅限练习/演示)
纯 CSS 实现最简单,但交互逻辑受限:鼠标移开就消失,无法保持状态,也不支持键盘操作,实际项目中基本不用。
使用 PptxGenJS 和 Python 解析,将结构化的 HTML/CSS 幻灯片内容转换为原生、可编辑的 PowerPoint(.pptx)演示文稿。
容易踩的坑在于结构强耦合 —— 内容区必须是标签同级后续元素,且顺序固定,用 nth-child(n) 控制显隐,一旦 DOM 变动就失效。
- 只适用于单层、静态、非关键路径的展示(比如官网 banner 下的小提示区)
- 无法与 URL 同步,刷新页面后状态丢失
- 不满足无障碍要求:
role="tab"、aria-controls等语义属性无法通过 hover 激活 - 移动端无效,因为没有 hover 状态
为什么不用 display: none 切换动态内容?
很多教程直接写 .tab-pane { display: none; },但若面板里有 <iframe></iframe>、<video></video> 或带输入框的表单,这么做会导致资源暂停、状态丢失。
真正要兼顾功能与体验,得换思路:用 visibility: hidden + position: absolute 隐藏内容,再配合 aria-hidden="true" 和 tabindex="-1" 保证可访问性。
-
visibility: hidden不脱离文档流,iframe 仍可加载、video 保持播放状态 - 必须加
position: absolute避免留白占位,否则页面会“跳动” - 切不可只改样式,要同步更新
aria-hidden和tabindex,否则屏幕阅读器会读出隐藏内容 - 键盘用户依赖
ArrowLeft/ArrowRight切换标签,这一步必须用 JS 补全,纯 CSS 做不到
纯 CSS 标签页的边界很清晰:能解决静态展示,但只要涉及状态保持、无障碍、URL 同步或动态资源,就得引入 JS。别为了“无 JS”硬扛,该加逻辑时就加。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










