原生单选框无法直接设置 border-radius 或 background-color,因浏览器对其样式强封装;需隐藏原生 input(用 opacity:0 + position:absolute + pointer-events:none),再通过 label::before/after 绘制自定义样式,并确保 html 中 input 在 label 前且 id/for 匹配。

直接给 input[type="radio"] 加 border-radius 或 background-color 无效——浏览器根本不响应这些样式,这不是你写错了,是原生控件的限制。
为什么不能直接改 .form-check-input 或 input[type="radio"] 的样式
所有现代浏览器都对原生单选框的视觉渲染做了强封装。你写的 border、background、transform 等几乎全部被忽略,只保留极有限的尺寸和透明度控制(比如 opacity)。这不是 Bug,是规范行为。想“画”出新样式,必须绕过它,而不是对抗它。
隐藏原生 input 的正确姿势:别用 display: none
display: none 和 visibility: hidden 会切断键盘焦点(Tab 切换失效)和屏幕阅读器支持,属于可访问性事故。推荐组合:
-
position: absolute把它移出文档流 -
opacity: 0让它不可见但保留交互区域 -
pointer-events: none防止遮挡下方内容 - 更稳妥的现代写法:
clip: rect(0 0 0 0)+clip-path: inset(50%)(Chrome 107+ / Firefox 111+ 支持良好)
同时确保 label 有 position: relative,否则伪元素无法精确定位。
用 ::before / ::after 绘制圆圈和选中点
核心逻辑靠相邻兄弟选择器触发:input:checked + label::after。这意味着 HTML 结构里 input 必须在 label 前面,且两者同级:
<div class="form-check"> <input class="form-check-input" type="radio" name="size" id="size-lg" value="lg"><label class="form-check-label" for="size-lg">Large</label> </div>
关键 CSS 片段:
.form-check-input {
position: absolute;
opacity: 0;
pointer-events: none;
}
.form-check-label {
position: relative;
padding-left: 28px;
}
.form-check-label::before {
content: '';
position: absolute;
left: 0; top: 50%;
transform: translateY(-50%);
width: 18px; height: 18px;
border: 2px solid #6c757d;
border-radius: 50%;
}
.form-check-input:checked + .form-check-label::after {
content: '';
position: absolute;
left: 5px; top: 50%;
transform: translateY(-50%);
width: 8px; height: 8px;
background-color: #0d6efd;
border-radius: 50%;
}
注意:::before 和 ::after 默认是 inline-level,不支持宽高,所以必须加 position: absolute 或 display: block 才能生效。
最容易被忽略的三个细节
一是 id 和 for 必须严格匹配(大小写敏感),漏一个字符就点不动;二是伪元素的定位依赖父容器的 position: relative,没加就飘走;三是如果用了 input 嵌套在 label 内的写法(如 <label><input>文本</label>),:checked + label 会失效,得改用 input:checked::after 并手动控制 input 的尺寸与定位——这种结构反而更难调。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











