peer-checked 不触发的根本原因是结构不满足硬性条件:①input必须是原生可交互控件且有name属性;②input与目标元素须同级、同父、input在前、中间无包裹或空白节点;③input不可用hidden或display:none隐藏。

peer类只能让同级、紧邻、在它之后的兄弟元素响应状态,写错DOM顺序或加错位置,样式就完全不生效。
peer-checked 为什么总不触发?检查这三点
peer本身不产生任何状态,它只是个锚点;真正起作用的是 peer-checked 这类工具类,但它们只对满足硬性结构条件的元素生效:
-
input必须是原生可交互控件(<input type="checkbox">或<input type="radio">),且必须有name属性(哪怕只有一个 radio 也要写) -
input和目标元素必须处于**同一父容器内、同级、且 input 在前、目标在后**——中间不能有 wrapper<div>、<code><label></label>,也不能有空格/换行产生的匿名文本节点 -
input不能用hidden属性或display: none隐藏(会脱离渲染树),推荐用sr-only或opacity-0 w-0 - ❌ 错误:
<label><input type="checkbox" class="peer"></label><div class="peer-checked:bg-blue-500">内容</div>→ input 被 label 包住,和 div 不是兄弟 - ❌ 错误:
<div><input type="checkbox" class="peer"></div> <div class="peer-checked:bg-blue-500">内容</div>→ input 和 div 不同级 - ❌ 错误:
<input type="checkbox" class="peer hidden"><div class="peer-checked:bg-blue-500">内容</div>→hidden属性导致 Safari 等浏览器跳过状态检测 - ✅ 正确:
<input type="checkbox" name="toggle" class="peer sr-only"><div class="peer-checked:bg-blue-500">内容</div>
常见错误结构 vs 正确写法
这些写法看着差不多,但只有最后一个能触发 peer-checked:bg-blue-500:
一个 peer 可以联动多个兄弟元素,但得各自声明
peer-checked 不是广播机制,每个目标元素都得显式加对应类。比如控制文字、按钮、图标三处变化,结构必须是:
<input type="checkbox" name="agree" class="peer sr-only"><label class="peer-checked:text-blue-600">我已阅读并同意</label> <button class="peer-checked:opacity-100 opacity-50">提交</button> <span class="peer-checked:block hidden">✅ 已确认</span>
三个目标元素都在 input 后面、同级、无间隔,各自带 peer-checked: 前缀,互不影响。想跨父容器控制?得换 group + group-data-[state] 或 JS。
移动端和可访问性容易被忽略的细节
隐藏 checkbox 后,用户实际点击区域极小,必须配 <label for="id"></label> 扩大热区;iOS Safari 对 :checked 状态更新有时延迟,若菜单闪动,可用 max-h-0 / peer-checked:max-h-96 替代 hidden / peer-checked:block,并加 will-change: transform 优化渲染。另外,sr-only 是语义化隐藏的首选——它保持元素可聚焦、可读取,而 opacity-0 w-0 在某些屏幕阅读器下可能失效。











