peer-checked 实现单选切换的本质是利用已勾选 radio 的同级后续兄弟元素(peer)响应 peer-checked:xxx 样式;结构必须严格为 input→peer 元素(同父、同级、input 在前),且 input 需有 name 属性、不可 hidden/opacity-0(可用 sr-only)。

用 peer-checked 配合 input[type="radio"] 实现视觉切换
单选切换效果的本质是:点击某个选项时,隐藏/显示对应内容,或改变其他元素样式。Tailwind 的 peer-checked 就是为此设计的——它只作用于紧跟在已勾选 input[type="radio"] 后面的兄弟元素(即 peer),且仅当该 radio 被选中时生效。
关键不是“怎么写 class”,而是结构必须严格满足:input → label 或 div(带 peer)→ 目标元素(用 peer-checked:xxx 控制)。顺序错、层级嵌套深、中间插入无关标签都会让 peer-checked 失效。
- 确保
input和目标元素是同级兄弟关系,且目标元素在input之后 -
input必须有name属性,否则无法互斥 - 不要给
input加hidden或opacity-0,否则部分浏览器下peer-checked不触发(可用sr-only替代)
为什么 peer-checked 不生效?常见 DOM 结构陷阱
最常踩的坑是误以为 “父容器里任意位置都能响应”。实际上 peer 查找只发生在同一父级下的后续兄弟节点,不跨层、不回溯、不找子元素。
错误示例:
—— 因为 input 被包在 div 里,和目标 div 不是兄弟,peer-checked 完全不工作。
- 正确结构必须是:内容
- 如果要用
label包裹input,那目标元素得放在label外部、同级后面,不能塞进label内部 - 多个 radio 共享一个
name,但每个都要配自己对应的peer-checked目标块,不能复用同一个 class 控制多个不同区域
配合 group / group-data-[state] 做更灵活的状态联动
当单选影响的不只是紧邻元素,而是更深层或更远的节点时,peer-checked 就不够用了。这时可以用 group + group-data-[state](需启用 data-* 插件)或者直接用 JS 控制 data 属性,再用 Tailwind 响应。
但注意:纯 CSS 方案里,group 要求所有相关元素被同一个父容器包裹,且触发元素(radio)必须在该容器内;而 peer-checked 不要求包裹,只要求同级顺序。
- 如果结构允许,优先用
peer-checked,零 JS、无状态管理负担 - 如果要切换多个非相邻区块、或需要动画过渡(比如 height 变化),
peer-checked对height等不可动画属性支持差,得搭配max-h-0/max-h-96和overflow-hidden - Tailwind v3.4+ 支持
has-[:checked](父容器内任一子 radio 被选中),但兼容性不如peer-checked,慎用于生产环境
实际可运行的小例子:三栏单选切换内容区
下面这段 HTML 能直接跑,点击任一 radio,下方对应文字块高亮,其余淡出:
<div class="space-y-2"> <input type="radio" name="view" value="a" class="peer sr-only"><label class="peer-checked:bg-indigo-100 px-3 py-1 rounded cursor-pointer">选项 A</label> <p><input type="radio" name="view" value="b" class="peer sr-only"><label class="peer-checked:bg-indigo-100 px-3 py-1 rounded cursor-pointer">选项 B</label></p> <p></p> <div class="mt-4 p-4 bg-gray-50 rounded"> <p class="text-gray-500 peer-checked:text-indigo-700">这是 A 的内容</p> <p class="text-gray-500 opacity-30 peer-checked:opacity-100">这是 B 的内容</p> </div> </div>
注意:两个 是并列的,都直接受各自前面 input 的 peer-checked 影响。第一个 p 响应第一个 input,第二个 p 响应第二个 input。顺序和配对必须手动对齐。
这种写法看着简单,但一旦 radio 和目标内容不在同一组父子链里,或者想复用同一套 class 控制不同区域,就得切到 JS 维护状态——这时候别硬撑 CSS,该加 useState 就加。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











