:checked伪类仅匹配用户实际选中的radio/checkbox,不依赖JS且不受disabled影响,但只能选择同级或后续兄弟元素,需严格采用label包裹input的HTML结构,并用display:none隐藏原生控件以保障可访问性。

为什么:checked伪类能控制表单状态
:checked 只匹配用户实际选中的 <input type="radio"> 或 <input type="checkbox"> 元素,它不依赖 JavaScript,也不受 disabled 状态影响(disabled 元素不会触发 :checked)。但关键限制是:它只能向上影响**同级或后续兄弟元素**,不能反向操作父容器或前序元素。这意味着自定义样式必须基于“隐藏原生控件 + 用相邻兄弟选择器关联 label”这一结构。
HTML 结构必须严格按 label + input 顺序写
常见错误是把 <input> 放在 <label> 里,或颠倒顺序。正确写法只有一种可靠模式:
<label> <input type="checkbox" id="agree"> 我同意条款 </label>
这样 input 是 label 的第一个子元素,才能用 input:checked + * 或 input:checked ~ * 控制后续内容。如果写成:
<input type="checkbox" id="agree"> <label for="agree">我同意条款</label>
那必须用 input#agree:checked ~ label,但前提是 label 确实在 input 后面且同级——稍一嵌套就失效。
立即学习“前端免费学习笔记(深入)”;
隐藏原生控件后,用 ::before/::after 绘制自定义外观
直接设置 input { display: none } 最安全;用 opacity: 0 或 position: absolute; left: -9999px 容易引发焦点、可访问性或点击区域问题。
接着对 label 设置相对定位,再用 label::before 绘制未选中状态的方框/圆圈,用 input:checked + label::before 覆盖样式:
- 复选框常用
content: "✓"或背景色填充 - 单选框用
border-radius: 50%+background实现实心圆点 - 务必加
cursor: pointer到label,否则用户无法直观感知可点击 - 别忘了
label:hover::before提供视觉反馈,否则体验割裂
无障碍与浏览器兼容的硬性注意事项
:checked 在 IE9+、Edge、Chrome、Firefox、Safari 均支持,但 Safari 对 input[type="radio"]:checked ~ label::after 的渲染偶有延迟(尤其配合 transition 时),建议避免对伪元素做复杂动画。
真正容易被忽略的是可访问性:
- 必须保留
for属性或显式嵌套,确保屏幕阅读器能关联 label 和 input - 不能仅靠颜色区分选中/未选中状态,要叠加图标、粗细或位置变化(比如 ✓ 出现 vs 消失)
- 键盘 Tab 进入后,
input仍需获得焦点,所以display: none是唯一不影响焦点流的方式 - 若用 JS 动态插入选项,
:checked不会响应 DOM 变化——它只响应用户真实交互,这点和 JS 的 checked 属性不同
纯 CSS 方案能跑通,但一旦需要联动其他组件(比如选中 A 就禁用 B)、或校验状态,就得切回 JS。伪类不是万能状态管理器,它只忠实地反映当前 DOM 中的 checked 属性值。


















