peer-checked仅作用于同级、紧邻后续兄弟元素,要求input与目标元素同父级、无间隔节点、input需有name属性且不可用display:none隐藏。
peer类只认紧邻的后续兄弟元素,不跨层也不回溯
peer-checked这类变体不是“监听整个父容器里谁被选中”,而是 CSS 原生选择器
和
的语法糖。它只对满足两个硬性条件的元素生效:一是目标元素必须和
处于**同一父级、同级、且在它之后**;二是中间不能插入任何其他元素(包括文本节点、注释、空格换行产生的匿名文本节点)。
错误结构:
→ label 把 input 包住了,input 和 div 不是兄弟,失效
更隐蔽的错误:
+ .target~ .target内容
→ 换行产生的文本节点打断了“紧邻”关系,部分浏览器下失效
正确写法必须是:
内容
,中间零间隔
input必须有name属性,且不能是hidden或opacity-0
peer-checked 依赖原生表单控件的交互状态,而
:checked
伪类在无
name
的 radio/checkbox 上不会稳定触发(浏览器认为它不属于任何组,无法互斥,状态不可靠)。同时,
hidden
属性或
opacity-0
会令某些浏览器(尤其是 Safari)跳过状态更新检测,导致 peer-checked 完全不响应。
name
是强制要求,哪怕只用一个 radio 也要写,例如:
隐藏 input 推荐用
sr-only
(语义化隐藏),而不是
hidden
或
opacity-0
—— 它通过 clip + absolute + overflow 实现视觉隐藏,但保持可聚焦、可检查
如果用了
display: none
,peer-checked 一定失效,因为该元素已脱离渲染树
多个radio共用name时,每个都要配独立的目标块
peer-checked 不是“广播式”状态,而是逐个绑定。同一个
name
下的多个
,各自只能控制自己后面紧邻的那个(或那组连续的)兄弟元素,不能让一个 class 控制多个不同位置的内容块。
错误做法:所有 radio 都指向同一个
→ 只有第一个 radio 后面那个 div 会被影响,其余无效
正确做法:每个 radio 后面都放自己专属的目标容器,例如:
A内容
,再下一个 radio 同理
若需复用逻辑,应靠结构复用(如用 JS 渲染相同结构),而非靠 class 复用
想控制非紧邻或深层子元素?peer不够用,得换方案
peer-checked 的能力边界非常清晰:只能影响**同级、后续、紧邻**的兄弟。一旦目标元素嵌套在 div 里、或隔了两层、或在父容器另一侧,它就完全无能为力。这时候别硬扛,该上别的机制。
Trae win
Trae Windows 官方版本现已全面支持 Win10 和 Win11 系统(64位)。国内开发者可直接访问 Trae 中文官网(trae.cn 或 trae.com.cn),一键下载官方正版 .exe 安装包,享受国内直连的高速稳定体验。安装过程极其简便,双击即可运行,并支持一键无缝导入 VS Code 或 Cursor 的原有主题、快捷键及插件配置。登录支持手机号、微信或稀土掘金账号。内置免费的豆包与 DeepSeek 等顶级大模型,让你开箱即用,轻松开启高效的 AI 智能编程之旅。
下载
立即学习
“
前端免费学习笔记(深入)
”;
目标在深层:用
group
+
group-data-[state]
(需启用
data-*
插件),把状态挂到共同父容器上,再用变体控制后代
目标在前面或跨父级:CSS 本身不支持选前一个兄弟,
:has()
尚未普及(Firefox 不支持,Safari 有限),此时 JS 设置 data 属性是最稳的路
复杂交互(如联动多个区域、带过渡延迟):peer/group 能覆盖 70% 场景,剩下 30% 直接用
data-active
+ Tail
win
d 的
data-[active]:xxx
更可控
真正卡住人的往往不是 class 写错,而是 DOM 顺序肉眼难辨——比如 JSX 中一行写完还是换行,Pug 模板里缩进是否引入了空格节点,这些细节在开发者工具里未必直观显示。调试时先看 computed styles 里有没有 :checked 生效,再一层层往上查 parent、sibling 关系,比反复改 class 有效得多。
