直接给 input[type="radio"] 加样式无效,因为浏览器硬编码渲染使其 width、height、background 等样式被忽略;需隐藏原生控件,通过 input:checked + label 控制自定义样式,并兼顾可访问性与键盘支持。

为什么直接给 input[type="radio"] 加样式无效
因为浏览器对原生 <input type="radio"> 的渲染是硬编码的,width、height、background 等样式基本被忽略,甚至 display: none 之后再用 ::before 也容易失焦或无法触发状态变化。真正起作用的是「隐藏原生控件 + 借助相邻兄弟选择器 + 用 label 触发」这套组合。
必须用 input + label 结构配合 :checked
核心逻辑是:把 input 隐藏(position: absolute; opacity: 0),然后通过 input:checked + label 或 input:checked ~ label(取决于 DOM 顺序)来控制自定义样式的显示状态。注意两点:
-
label必须显式绑定for属性或包裹input,否则点击无效 -
:checked只对input[type="radio"]和input[type="checkbox"]生效,不支持伪元素直接模拟选中态 - 如果使用
input + label(相邻兄弟),label必须紧接在input后面;若用~,则只要在同一父容器内即可
::before 和 ::after 在 label 上画圆点要注意层级和尺寸
常见错误是自定义圆点大小不对、未居中、或被遮挡。推荐做法是把 label 设为 position: relative,再用 label::before 绘制外圈,label::after 绘制内点,并用 transform: translate(-50%, -50%) 居中。关键参数:
-
label::before:设content: ""、width/height控制外圈直径、border: 2px solid #999 -
label::after:只在input:checked + label::after中定义,background: #007bff,width/height约为外圈的 40%~60% - 务必加
pointer-events: none到伪元素上,避免干扰点击区域
无障碍与键盘支持不能只靠视觉
仅靠鼠标点击 label 是不够的。用户按 Tab 进入焦点时,原生 input 仍需可聚焦;按 Space 应能切换选中态。所以:input 不能用 display: none(会移除可访问性树),而要用 position: absolute; clip: rect(0 0 0 0); clip-path: inset(100%); 等方式隐藏但保留语义。同时,用 label:focus-within 或 input:focus + label 添加焦点轮廓,否则键盘用户看不到当前焦点在哪。
立即学习“前端免费学习笔记(深入)”;
真正难的不是画个圆点,而是让屏幕阅读器读出选项含义、让键盘操作流畅通、让高对比度模式下仍可识别——这些细节往往在测试阶段才暴露出来。


















