根本原因是display: none会彻底移除元素渲染,导致:checked状态在旧版Safari中无法被识别;应改用position: absolute; opacity: 0; pointer-events: none隐藏checkbox,确保其逻辑“存活”并可触发。

为什么用 input[type="checkbox"] 而不是 display: none 直接切菜单
因为 display: none 会彻底移除元素渲染,导致 :checked 状态在部分旧版 Safari 中无法被 CSS 选择器识别——点了没反应,不是你写错了,是浏览器跳过了隐藏 checkbox 的状态更新。必须让 checkbox 在视觉上不可见但逻辑上“活着”。
正确做法是用 position: absolute; opacity: 0; pointer-events: none; 隐藏它,既不占布局空间,又保留可触发性。同时 label 必须和 input 显式关联:label[for="nav-toggle"] 或直接把 input 包进 label 里(更稳妥,避免 ID 冲突)。
input:checked + .menu 和 input:checked ~ .menu 怎么选
关键看 HTML 结构中 menu 元素是否「紧邻」在 input 后面:
- 如果
<input><label></label><nav class="menu"></nav>→ 用input:checked ~ .menu(~ 是后续所有兄弟) - 如果
<input><nav class="menu"></nav>中间没其他元素 → 可用input:checked + .menu(+ 只认下一个紧邻兄弟) - 如果 menu 在 nav 内部,而 input 在外部 → 两种都无效,得把 input 移到 nav 同级或内部,否则选择器根本匹配不到
为什么不能用 height: 0 ↔ auto 做过渡动画
height: auto 不是一个可计算的数值,CSS 过渡引擎没法插值,写了 transition: height 0.3s 也只会瞬间切换。真正能动起来的是有明确中间状态的属性:
立即学习“前端免费学习笔记(深入)”;
-
max-height:关闭设max-height: 0; overflow: hidden,展开设一个“够用但不过大”的值,比如max-height: 300px(比最大可能菜单高即可) - 避免设
max-height: 1000px—— 动画会变慢,且若内容少,会看到明显“拉伸感” - 若菜单含异步加载的图片或字体,初始
max-height不够会截断,可在展开后加padding-bottom: 1px强制重排微调
移动端点击后背景不能滚动,是不是漏了什么
不是 CSS 的问题,是交互逻辑缺一环:纯 Checkbox 方案本身不控制 body 滚动,但如果你手动加了 body { overflow: hidden } 来防穿透,就必须配 JS 恢复——而 Checkbox 是无 JS 的。所以真正容易被忽略的点是:
- Checkbox 方案默认不锁 body 滚动,也不防点击穿透;如需防穿透,得额外加遮罩层(
.overlay),并用pointer-events: none控制其开关 - 遮罩层必须是
position: fixed,且 z-index 高于菜单但低于弹窗类元素 - 如果用了
transform移动菜单(比如侧滑),记得加will-change: transform,否则 iOS Safari 上动画可能卡顿或失效


















