:checked只能作用于同一父容器中位于其后的同级兄弟元素,非后代、非父级;input必须在目标元素之前,且不能用display:none隐藏,label须通过for或直接嵌套正确绑定。

input位置错了,:checked根本选不到目标元素
:checked只能影响它在DOM中**后续同级兄弟元素**,不是后代、不是父级、更不是任意位置的同名元素。很多人把放在
:checked + .content永远不匹配。
必须保证:input和目标元素是同一父容器下的直接子节点,且input在前、目标在后。比如:
<div class="panel"> <input type="checkbox" id="toggle-1"><div class="panel-content">...</div> </div>
错误结构示例:<label><input><div class="content"></div></label>——此时div是input的后代,不是兄弟,:checked + .content无效。
label没真正绑定input,点击根本不改checked状态
label点击能触发:checked,前提是它和input之间有合法绑定关系。浏览器不会“猜”哪个label对应哪个input。
- 用
for属性时,id值必须只含字母、数字、下划线、短横线(如id="nav-toggle"),id="menu[1]"或id="user.name"会直接失效 - 嵌套写法必须是
<label><input>文字</label>,且input是label的**直接子元素**;中间插个<span></span>就可能断链 - 别用
onclick手动改checked属性——这不会触发:checked伪类,因为伪类只响应用户真实交互或click()调用
隐藏input的方式破坏了:checked识别
用display: none或opacity: 0; pointer-events: none隐藏复选框,在部分安卓原生浏览器里会切断状态监听链,导致:checked完全不响应。
正确做法是让input保留在文档流中但视觉不可见:
- 推荐:
position: absolute; left: -9999px; width: 1px; height: 1px; - 禁用:
display: none、clip-path: inset(50%)(部分安卓支持不全) - 如果必须用
opacity,至少保留pointer-events: auto,并确保label有cursor: pointer
安卓和IE老版本有硬性限制,不能只靠CSS兜底
IE8及以下完全不识别:checked,IE9–10不支持select或option上的:checked;安卓旧版浏览器(如Samsung Internet)存在状态更新延迟,尤其当页面有大量transform或will-change时。
这些场景下,纯CSS路径必然失效,必须引入JS模拟:
- 监听
change事件,而非click(键盘空格键也要支持) - 初始化时根据
el.checked补上is-checked类 - radio组要手动清掉同
name下其他项的类,否则多个都亮 - 所有原CSS中的
:checked选择器,都得替换成.is-checked,漏一处就挂一处
最易被忽略的是:安卓原生浏览器里,:checked的触发依赖于input是否“被用户真实操作”,JS赋值el.checked = true后若不手动el.dispatchEvent(new Event('change')),样式不会更新。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











