peer-checked仅作用于同级、紧邻后续兄弟元素,要求input与目标元素同父级、无间隔节点、input需有name属性且不可用display:none隐藏。

peer类只认紧邻的后续兄弟元素,不跨层也不回溯
peer-checked这类变体不是“监听整个父容器里谁被选中”,而是 CSS 原生选择器 + .target 和 ~ .target 的语法糖。它只对满足两个硬性条件的元素生效:一是目标元素必须和 <input class="peer"> 处于**同一父级、同级、且在它之后**;二是中间不能插入任何其他元素(包括文本节点、注释、空格换行产生的匿名文本节点)。
- 错误结构:
<label><input type="radio" class="peer"></label><div class="peer-checked:bg-blue-500">内容</div>→ label 把 input 包住了,input 和 div 不是兄弟,失效 - 更隐蔽的错误:
<input type="radio" class="peer"><!-- 空格或换行 --><div class="peer-checked:bg-blue-500"> → 换行产生的文本节点打断了“紧邻”关系,部分浏览器下失效<li>正确写法必须是:<code><input type="radio" name="tab" class="peer sr-only"><div class="peer-checked:bg-blue-500">内容</div>,中间零间隔 -
name是强制要求,哪怕只用一个 radio 也要写,例如:<input type="radio" name="filter" class="peer sr-only"> - 隐藏 input 推荐用
sr-only(语义化隐藏),而不是hidden或opacity-0—— 它通过 clip + absolute + overflow 实现视觉隐藏,但保持可聚焦、可检查 - 如果用了
display: none,peer-checked 一定失效,因为该元素已脱离渲染树 - 错误做法:所有 radio 都指向同一个
<div class="peer-checked:bg-red-500"> → 只有第一个 radio 后面那个 div 会被影响,其余无效<li>正确做法:每个 radio 后面都放自己专属的目标容器,例如:<code><input name="tab" value="a" class="peer sr-only"><div class="peer-checked:bg-blue-500">A内容</div>,再下一个 radio 同理 - 若需复用逻辑,应靠结构复用(如用 JS 渲染相同结构),而非靠 class 复用
- 目标在深层:用
group+group-data-[state](需启用data-*插件),把状态挂到共同父容器上,再用变体控制后代 - 目标在前面或跨父级:CSS 本身不支持选前一个兄弟,
:has()尚未普及(Firefox 不支持,Safari 有限),此时 JS 设置 data 属性是最稳的路 - 复杂交互(如联动多个区域、带过渡延迟):peer/group 能覆盖 70% 场景,剩下 30% 直接用
data-active+ Tailwind 的data-[active]:xxx更可控
input必须有name属性,且不能是hidden或opacity-0
peer-checked 依赖原生表单控件的交互状态,而 :checked 伪类在无 name 的 radio/checkbox 上不会稳定触发(浏览器认为它不属于任何组,无法互斥,状态不可靠)。同时,hidden 属性或 opacity-0 会令某些浏览器(尤其是 Safari)跳过状态更新检测,导致 peer-checked 完全不响应。
多个radio共用name时,每个都要配独立的目标块
peer-checked 不是“广播式”状态,而是逐个绑定。同一个 name 下的多个 <input class="peer">,各自只能控制自己后面紧邻的那个(或那组连续的)兄弟元素,不能让一个 class 控制多个不同位置的内容块。
想控制非紧邻或深层子元素?peer不够用,得换方案
peer-checked 的能力边界非常清晰:只能影响**同级、后续、紧邻**的兄弟。一旦目标元素嵌套在 div 里、或隔了两层、或在父容器另一侧,它就完全无能为力。这时候别硬扛,该上别的机制。
真正卡住人的往往不是 class 写错,而是 DOM 顺序肉眼难辨——比如 JSX 中一行写完还是换行,Pug 模板里缩进是否引入了空格节点,这些细节在开发者工具里未必直观显示。调试时先看 computed styles 里有没有 :checked 生效,再一层层往上查 parent、sibling 关系,比反复改 class 有效得多。











