peer-checked 不生效是因为 checkbox 必须是同级前驱元素且不可 hidden;iOS Safari 动画抖动需用固定 max-h 值并加 will-change;可访问性需 JS 配合焦点管理。

纯 CSS 实现响应式导航菜单,必须用 <input type="checkbox"> 作状态源,peer 类只对它生效;直接写 onclick 切换 class 或用 hidden 属性隐藏 checkbox 都会导致 peer-checked:* 规则失效。
为什么 peer-checked 不生效?检查 checkbox 是否被正确“桥接”
Tailwind 的 peer-checked 不监听 click,只响应 :checked 状态。所以必须让 checkbox 成为按钮和菜单的共同兄弟节点,且顺序在前:
-
<input type="checkbox" id="menu-toggle" class="peer sr-only">—— 必须有id,不能加hidden属性或display: none,否则屏幕阅读器无法聚焦、:checked状态不可访问 -
<label for="menu-toggle">☰</label>——for值必须与 checkbox 的id完全一致,点击才触发勾选 -
<nav class="peer-checked:opacity-100 ...">—— 必须是 checkbox 的**同级后继元素**(不是子元素),且中间不能插入其他标签打断兄弟关系
移动端菜单闪动或收不回去?iOS Safari 的渲染陷阱
iOS Safari 对 max-h-0 + peer-checked:max-h-96 的过渡有渲染抖动,尤其在快速连点时。这不是 bug,而是浏览器对 height 动画的重排策略问题:
- 改用
max-h-0→peer-checked:max-h-[500px](固定数值),避免max-h-full这类动态值 - 加
will-change: transform, opacity到菜单元素上,提前触发 GPU 渲染层 - 动画必须写在菜单本身:
transition-all duration-300 ease-in-out,不能只写在peer-checked:类里 - 收起后手动恢复焦点到按钮(
label.focus()),否则键盘用户会卡在空白处
桌面端菜单始终显示,但小屏下又想保留 hover 效果?断点嵌套要小心
别写 md:hover:bg-gray-100 这种混合断点+伪类的组合——Tailwind 2.x 不支持,会直接忽略。正确做法是分层控制:
立即学习“前端免费学习笔记(深入)”;
- 默认状态(小屏):
hover:bg-gray-100生效 - 大屏强制显示:
lg:flex lg:space-x-6,同时用lg:hover:bg-transparent覆盖 hover 样式(因为桌面端不需要 hover 高亮) - 如果需保留桌面 hover,改用
lg:hover:text-blue-600这类不影响布局的属性 - 避免在同一个元素上混用
hidden和flex:优先用md:flex hidden(默认隐藏,大屏显示),而不是hidden md:block(容易因 class 顺序冲突导致残留)
最易被忽略的是可访问性链路:checkbox 必须能被键盘 Tab 到达,label 必须可聚焦,菜单打开后焦点要自动移到第一个链接——这些都不能靠 CSS 完成,必须补少量 JS。


















