LuLu UI Edge版中文文档 » 单选框

文档 Github➹

单选框

安装与调用

单选框引入:

<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>

选中与禁用

模拟单选框的选中和禁用效果的实现和原生单选框一致,使用原生的 checkeddisabled 属性即可。

选中语法示意:

<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', '') 能否触发变化:

只有第一次有效

余额不足,还差 17 金币:

<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;
}

使用说明

  1. 引入组件 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>
  2. 使用 <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 {
    /* 禁用的样式 */                
}

余额不足,还差 17 金币:

<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>

余额不足,还差 17 金币:

<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