纯 CSS 实现 PPT 式全屏幻灯片切换必须用 position: absolute 堆叠 + opacity/visibility 双过渡 + 父容器 position: relative;缺任一条件都会导致错位、首张不显或点击穿透。

纯 CSS 实现 PPT 式全屏幻灯片切换,position: absolute 堆叠方案可行,但必须配合 opacity + visibility + transition,且父容器 position: relative 是硬性前提——漏掉这点,所有幻灯片会挤在左上角,第一张都可能不显示。
为什么只用 position: absolute 堆叠不行
堆叠只是让元素重叠,不等于“控制显隐”。常见问题包括:
-
display: none/block切换无过渡动画,transition对它完全无效 - 只调
z-index不改变渲染状态,旧幻灯片仍可被点击、聚焦、影响 tab 键顺序 - 没设
top: 0; left: 0;时,absolute元素可能因文档流残留偏移(尤其含内联文本的容器) - 父容器缺失
position: relative,所有子项将相对于body定位,错位不可避免
opacity 和 visibility 必须一起过渡
只写 transition: opacity 0.4s 会导致视觉残留或点击穿透:因为 visibility: hidden 立即生效,而 opacity: 0 是渐变过程。两者不同步就会“闪一下”或“半透明可点”。
- 必须同时过渡:
transition: opacity 0.4s ease, visibility 0.4s; -
visibility的过渡时间必须和opacity完全一致,不能写成visibility 0.1s -
.slide初始状态必须是opacity: 0; visibility: hidden;,否则:checked ~ .slide无法匹配第一张 - 别用
pointer-events: none替代visibility——它不随动画变化,容易误关交互
:checked + ~ 控制显隐时 DOM 结构不能错
这个纯 CSS 方案依赖选择器能力,对 HTML 结构极其敏感:
立即学习“前端免费学习笔记(深入)”;
- 所有
<input type="radio">必须同名,例如name="slide",否则无法互斥选中 -
<input>必须在所有.slide元素之前,且在同一父级下(不能跨层嵌套) - 必须用
~(通用兄弟选择器),不是+(相邻兄弟)——因为中间常有<label>或辅助元素 - 若用
<label for="xxx">,确保for属性值与对应input的id严格一致
移动端触摸区域小?别靠 radio 按钮本身响应
原生 <input type="radio"> 在移动端点击区域极小,用户几乎点不中。必须靠 <label> 扩展可点范围:
-
<label>必须包裹完整内容,或至少明确设置for="xxx" - 给
label加display: block和足够内边距(如padding: 20px) - 避免在
label内再套其他定位元素,干扰点击热区计算 - 测试时用真机 Safari / Chrome,部分 Android 浏览器对
for绑定支持不稳定
真正难的不是堆叠或过渡,而是结构容错性:DOM 顺序错一位、父容器少一个 relative、visibility 过渡时间差 0.01 秒,都会导致第一张不显示、点击失效或动画卡顿。这些细节不手动验证一遍,上线后用户一滑就懵。


















