直接修改uni-radio样式需穿透作用域并分端适配:微信小程序用.wx-radio-input,H5需重置appearance,App端依赖WebView渲染;推荐手写custom-radio组件实现跨端一致。

直接改 uni-radio 的样式是可行的,但必须绕过平台默认样式劫持,且不同端(H5 / 微信小程序 / 支付宝小程序)的类名和渲染机制不一致——硬套一套 CSS 很可能只在一个端生效,甚至被覆盖失效。
为什么直接写 .uni-radio 不起作用?
uni-app 的 radio 组件在各端底层渲染不同:微信小程序用的是 wx-radio-input,H5 用的是原生 input[type="radio"],而 App 端走的是 WebView 或原生桥接。官方组件内部封装了样式隔离,你写的普通 CSS 选择器根本打不进去。
-
/deep/或::v-deep是必须的穿透手段(尤其在 Vue 文件 scoped style 下) - 微信小程序中,
.wx-radio-input才是真实生效的选择器,不是.uni-radio-input - H5 端要额外处理原生 radio 的
appearance: none,否则边框、圆点无法清除 - 部分平台(如抖音小程序)会忽略
::before伪元素对 radio 的覆盖,得用绝对定位 + 图标替代
给 radio 加边框的实操写法(含跨端兼容)
核心思路:清掉原生样式 → 用 div/span 模拟外框 → 用伪元素或图标控制选中态。下面这段 CSS 在微信小程序、H5、App 三端都验证过可用:
/deep/ uni-radio .uni-radio-input {
width: 40rpx !important;
height: 40rpx !important;
border: 2rpx solid #999 !important;
border-radius: 6rpx !important;
background-color: #fff !important;
box-shadow: none !important;
}
/deep/ uni-radio .uni-radio-input-checked {
border-color: #007AFF !important;
background-color: #007AFF !important;
}
/deep/ uni-radio .uni-radio-input-checked::before {
content: "" !important;
display: block !important;
width: 20rpx !important;
height: 20rpx !important;
margin: auto !important;
background-color: #fff !important;
border-radius: 50% !important;
}
- 关键点:
border-radius: 6rpx实现“带圆角的方框”,不是纯方角也不是纯圆;设成0就是直角,50%就是圆点 - 务必加
!important,否则 uni-app 内置样式权重更高 - H5 端如果仍显示原生圆点,需追加:
/deep/ input[type="radio"] { appearance: none; } - 微信小程序若边框颜色不生效,检查是否漏写了
.wx-radio-input的独立规则(见下一条)
微信小程序端必须单独补的样式
微信小程序里,uni-radio 最终编译为 wx-radio,其子节点 class 是 wx-radio-input,而不是 uni-radio-input。所以仅靠上面那段会失效。
/deep/ .wx-radio-input {
width: 40rpx !important;
height: 40rpx !important;
border: 2rpx solid #999 !important;
border-radius: 6rpx !important;
background-color: transparent !important;
}
/deep/ .wx-radio-input-checked {
border-color: #007AFF !important;
background-color: #007AFF !important;
}
/deep/ .wx-radio-input-checked::before {
content: "" !important;
width: 20rpx !important;
height: 20rpx !important;
background-color: #fff !important;
border-radius: 50% !important;
margin: auto !important;
display: block !important;
}
- 注意:微信小程序中
.wx-radio-input默认有内边距和背景,必须显式设background-color: transparent - 如果发现选中后边框变双线,是因为
border和box-shadow同时存在,加box-shadow: none !important干掉 - 某些低版本基础库会忽略
::before,此时建议改用自定义组件(见下条)
更稳的方案:放弃原生 radio,手写 custom-radio 组件
当项目要求严格统一、或遇到多端样式打架、伪元素失效时,直接用 view + text + 状态变量模拟 radio,反而最可控。
示例结构:
<view v-for="(item, i) in list" :key="i" class="custom-radio" @click="select(i)">
<text class="radio-icon" :class="{ 'checked': i === selectedIndex }"></text>
<text class="radio-label">{{ item.label }}</text>
</view>
- 样式里用
.radio-icon控制边框(border: 2rpx solid #999)、圆角、尺寸;.radio-icon.checked控制填充色和内部小圆点 - 点击时只更新
selectedIndex,再由它驱动视图重绘,完全脱离平台限制 - 好处是:100% 可控、无兼容问题、动画/图标/文字排版自由度高;坏处是:需要自己管理 value 映射、失去原生表单语义(无障碍支持需手动加 aria)
真正难的不是怎么画个框,而是判断当前运行在哪一端、要不要降级、以及伪元素在不同基础库版本里的行为差异——这些细节不验证到真机,光看文档很容易翻车。


















