peer-checked 失效主因是 html 结构不合规:input 必须为原生可交互控件且带 name 属性;input 与目标元素须同父同级、input 在前、中间无 wrapper 或空白节点;input 不可用 hidden 或 display: none 隐藏。

peer 类本身不触发任何样式,它只是为后续兄弟元素提供一个可被监听的锚点;真正起作用的是 peer-checked、peer-focus 这类带前缀的工具类,但它们只在严格满足 DOM 结构条件时才生效。
为什么 peer-checked 总是不生效?先查这三点
绝大多数失效问题都出在 HTML 结构上,不是 Tailwind 配置或 class 写错:
-
input必须是原生可交互控件(<input type="checkbox">或<input type="radio">),且必须带name属性(哪怕只有一个单选框也要写) -
input和目标元素必须同父、同级、input在前、目标在后——中间不能有 wrapper<div>、<code><label></label>,也不能有空格/换行产生的匿名文本节点 -
input不能用hidden属性或display: none隐藏(会脱离渲染树),推荐用sr-only或opacity-0 w-0
peer 联动多个元素时,每个目标都得显式声明状态类
peer 不是广播机制,不会自动影响所有后续兄弟。每个要响应的元素,都必须自己带上对应前缀,比如:
<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> <svg class="peer-checked:scale-100 scale-75"></svg>
这三个元素都在 input 后面、同级、无间隔,各自加了 peer-checked: 前缀,互不影响。少写一个,那个元素就完全不动。
想跨父容器控制?peer 不行,得换方案
peer 只认紧邻的后续兄弟,不跨层、不回溯、不找子元素。如果你需要让某个按钮点击后影响另一个 section 里的标题,或者控制嵌套很深的子组件,peer 就无能为力了:
- 结构允许时,优先用
group+group-data-[state](需启用data-* 插件)
- 更灵活或需动画过渡(如
height、<code>max-height)时,直接用 JS 控制data-属性,再由 Tailwind 响应 - 注意:
group要求所有相关元素被同一个父容器包裹,而peer不要求包裹,只要求同级顺序——这是关键取舍点
最常被忽略的是换行和空格:哪怕 <input> 和 <div> 看起来“挨着”,中间一个回车也会生成匿名文本节点,导致 <code>~ 相邻兄弟选择器失效。写的时候建议把这两行贴在一起,不换行、不缩进。











