安装与调用
单选框引入:
<link rel="stylesheet" href="https://qidian.gtimg.com/lulu/hope/ui/Radio/index.css">
模拟单选框
语法与基础效果
给原生的单选框元素添加 is="ui-radio"
属性。
<input type="radio" is="ui-radio">
<input type="radio" id="r1" name="radio" is="ui-radio"> <label for="r1">单选项</label>
选中与禁用
模拟单选框的选中和禁用效果的实现和原生单选框一致,使用原生的 checked
和 disabled
属性即可。
选中语法示意:
<input type="radio" is="ui-radio" checked>
禁用语法示意:
<input type="radio" is="ui-radio" disabled>
<input type="radio" id="r3" is="ui-radio" checked> <label for="r3">选中</label> <input type="radio" id="r4" is="ui-radio" disabled> <label for="r4">单选项4</label> <input type="radio" id="r5" is="ui-radio" disabled checked> <label for="r5">单选项5</label>
自定义单选样式
我们可以使用任意的 <image>
数据类型对单选框进行样式自定义。
方法是在任意的祖先级别的标签元素上设置 CSS 自定义属性 --ui-radio-default
/ --ui-radio-checked
就可以了。
例如下面这段 HTML 代码:
<form class="css-radio"> <input type="radio" id="ra" name="rc" is="ui-radio"><label for="ra">单选项A</label> <input type="radio" id="rb" name="rc" is="ui-radio"><label for="rb">单选项B</label> </form>
通过这么一段 CSS 代码(CSS 径向渐变图像)的设置:
.css-radio { --ui-radio-default: radial-gradient(transparent 0 calc(.625rem - 2px), #000 0 .625rem, transparent 0); --ui-radio-checked: radial-gradient(#000 0 .25rem, transparent 0 calc(.625rem - 2px), #000 0 .625rem, transparent 0); }
可以实现类似的样式效果:
我们也可以 CSS url()
函数图像自定义单选效果,包括 HTTPS 地址,转义 SVG 图像,或者 Base64 地址:
比方说下面这个点赞图标作为单选图形的例子。
<form class="like-radio">
<input type="radio" id="rl1" name="rl" is="ui-radio"><label for="rl1">给我点赞</label>
<input type="radio" id="rl2" name="rl" is="ui-radio"><label for="rl2">给我点赞</label>
</form>
.like-radio {
--ui-radio-default: url(https://imgservices-1252317822.image.myqcloud.com/image/011420220134219/1ccfd82f.svg);
--ui-radio-checked: url(https://imgservices-1252317822.image.myqcloud.com/image/011420220134219/d22b1d90.svg);
}
如果希望单选框未选中态没有图形显示,可以设置:
--ui-radio-default: url();
注意,自定义属性 --ui-radio-default
和 --ui-radio-checked
具有继承性,如果自定义的图形效果比较特殊,只针对当前元素,则自定义属性不要设置在层级过高的元素上,以免影响其他单选框元素。
单选列表
本组件和布局组件既可以相互独立,也可以联合使用,详见“既定布局”中的“选择列表”。
组件衍生与扩展
我们可以利用单选框的点击选中行为实现任意的唯一选择交互效果,先看实际的应用效果。
测试 radio.checked = true 能否触发样式变化:
测试 radio.setAttribute('checked', '') 能否触发变化:
只有第一次有效<form class="pay-form">
<p>余额不足,还差 <output>17</output> 金币:</p>
<ui-flex space="between">
<label class="pay-item">
<input type="radio" name="pay" value="100" is="ui-radio" extends>
<strong>100</strong>
<span>¥1</span>
<sup>赠100币</sup>
</label>
<label class="pay-item">
<input type="radio" name="pay" value="500" is="ui-radio" extends>
<strong>500</strong>
<span>¥1</span>
<sup>赠500币</sup>
</label>
<label class="pay-item">
<input type="radio" name="pay" value="1000" is="ui-radio" extends checked>
<strong>1000</strong>
<span>¥10</span>
<sup>赠1000币</sup>
</label>
</ui-flex>
</form>
.pay-form {
background-color: var(--ui-light);
padding: 1rem;
}
.pay-item {
display: grid;
flex: 0 1 calc((100% - 2rem) / 3);
background-color: #0001;
border-radius: 1rem;
padding: 1rem;
box-sizing: border-box;
text-align: center;
}
.pay-item strong {
font-size: 125%;
}
.pay-item span {
color: var(--ui-gray);
font-size: 87.5%;
}
.pay-item sup {
background-color: var(--ui-red);
grid-area: 1 / 1 / 2 / 2;
justify-self: end;
color: var(--ui-white);
margin: -1rem -1rem 0 0;
padding: 0 .25rem;
font-size: 75%;
}
/* 选中样式 */
.pay-item.active {
background-color: #fff;
box-shadow: inset 0 0 0 1px;
}
使用说明
-
引入组件 JS:
<script type="module" src="https://qidian.gtimg.com/lulu/hope/ui/Radio/index.js"></script>
或者:
<script type="module"> import 'https://qidian.gtimg.com/lulu/hope/ui/Radio/index.js'; </script>
-
使用
<label>
元素作为点击按钮,内部添加如下所示的单选框代码:<label> <input type="radio" name="any" is="ui-radio" extends> </label>
注意这里的
extends
属性是必须的,表示使用 JS 扩展单选框的能力。
此时 <label>
元素就会自动根据点击状态增减类名 .active
。
其中,<input>
元素并不一定需要是 <label>
的子元素,可以在页面的任意位置,不过此时需要通过 for
属性进行关联,示意:
<label class="active" for="any"></label> <input type="radio" id="any" is="ui-radio" extends checked>
实现原理
单选框元素设置 is="ui-radio"
属性后会变成内置自定义元素,如果同时还设置了 extends
属性,则每当单选框元素的选中态发生变化的时候,会自动寻找其对应的 <label>
元素,然后根据是否选中切换类名 .active
,根据是否禁用切换类名 .disabled
。
用代码示意就会是这样:
<!-- 类名 active 和 disabled 是组件添加的 --> <label class="active disabled"> <input type="radio" name="any" is="ui-radio" extends checked disabled> </label>
此时,就可以基于类名 .active
和 .disabled
实现我们需要的样式效果了。
不依赖组件实现
从技术角度讲,只需要 HTML 结构合理,纯 CSS 就能实现唯一选择交互效果,示意:
<!-- 外层只负责尺寸 --> <div class="layout"> <input type="radio" id="r" hidden> <!-- 这个才是主要样式 --> <label for="r" class="container"></label> </div>
:checked + .container { /* 选中的样式 */ } :disabled + .container { /* 禁用的样式 */ }
<form class="pay-form">
<p>余额不足,还差 <output>17</output> 金币:</p>
<ui-flex space="between">
<div class="pay-item">
<input id="rp1" type="radio" name="pay2" value="100" hidden>
<label class="pay-label" for="rp1">
<strong>100</strong>
<span>¥1</span>
<sup>赠100币</sup>
</label>
</div>
<div class="pay-item">
<input id="rp2" type="radio" name="pay2" value="500" hidden>
<label class="pay-label" for="rp2">
<strong>500</strong>
<span>¥1</span>
<sup>赠500币</sup>
</label>
</div>
<div class="pay-item">
<input id="rp3" type="radio" name="pay2" value="1000" hidden checked>
<label class="pay-label" for="rp3">
<strong>1000</strong>
<span>¥10</span>
<sup>赠1000币</sup>
</label>
</div>
</ui-flex>
</form>
.pay-form {
background-color: var(--ui-light);
padding: 1rem;
margin: 0 -1rem;
}
.pay-item {
flex: 0 1 calc((100% - 2rem) / 3);
}
.pay-label {
display: grid;
background-color: #0001;
border-radius: 1rem;
padding: 1rem;
box-sizing: border-box;
text-align: center;
}
.pay-label span {
color: var(--ui-gray);
font-size: 87.5%;
}
.pay-label sup {
background-color: var(--ui-red);
grid-area: 1 / 1 / 2 / 2;
justify-self: end;
color: var(--ui-white);
margin: -1rem -1rem 0 0;
padding: 0 .25rem;
font-size: 75%;
}
:checked + .pay-label {
background-color: #fff;
box-shadow: inset 0 0 0 1px;
}
或者使用单选框元素模拟变化的样式,此方法优点是 HTML 结构简单了,不足就是需要对单选框元素进行定位和样式设置,需要一定的 CSS 基本功,详见下面演示效果中的源码。
<label> <!-- input 元素模拟选中背景色和边框 --> <input type="radio" value="100"> </label>
<form class="pay-form">
<p>余额不足,还差 <output>17</output> 金币:</p>
<ui-flex space="between">
<label class="pay-item">
<input type="radio" name="pay3" value="100">
<strong>100</strong>
<span>¥1</span>
<sup>赠100币</sup>
</label>
<label class="pay-item">
<input type="radio" name="pay3" value="500">
<strong>500</strong>
<span>¥1</span>
<sup>赠500币</sup>
</label>
<label class="pay-item">
<input type="radio" name="pay3" value="1000" checked>
<strong>1000</strong>
<span>¥10</span>
<sup>赠1000币</sup>
</label>
</ui-flex>
</form>
.pay-form {
background-color: var(--ui-light);
padding: 1rem;
}
.pay-item {
display: grid;
flex: 0 1 calc((100% - 2rem) / 3);
padding: 1rem;
box-sizing: border-box;
text-align: center;
position: relative;
z-index: 0;
}
.pay-item [type="radio"] {
all: initial;
-webkit-appearance: none;
appearance: none;
position: absolute;
left: 0; top: 0;
width: 100%; height: 100%;
z-index: -1;
background-color: #0001;
border-radius: 1rem;
}
.pay-item span {
color: var(--ui-gray);
font-size: 87.5%;
}
.pay-item sup {
background-color: var(--ui-red);
grid-area: 1 / 1 / 2 / 2;
justify-self: end;
color: var(--ui-white);
margin: -1rem -1rem 0 0;
padding: 0 .25rem;
font-size: 75%;
}
/* 选中样式 */
.pay-item3 :checked {
background-color: #fff;
box-shadow: inset 0 0 0 1px;
}
以上演示的 3 种实现方法都是可以在项目中使用的,我的建议是这样的,如果你的 Web 页面是直出的,建议采用后面的两种 CSS 方法,交互体验会更好;如果你的 Web 页面是打包后的 JS 吐出的,则可以使用第 1 种自定义组件方法,结构更灵活,上手更简单。
原生单选框
如果希望某些场景还是使用原生的单复选框,不添加 is="ui-radio"
即可,示意:
<input type="radio" id="r6"><label for="r6">单选框6</label>
本页贡献者:
zhangxinxu