css

替换input type=radio 的默认样式

Posted by Jxx on March 23, 2018

一、前言

默认情况每个浏览器对input type=radio的表现都不一样,而且巨丑,今天就来介绍一种替换掉默认样式,但是还是使用<input>type=radio属性的方法

页面结构:

<div class="check-group">
    <input type="radio" id="xx1" name="lineName" value="choose1" checked="checked">
    <label for="xx1" class="ui-radio"></label>
    <label for="xx1">选项一</label>
</div>
<div class="check-group">
    <input type="radio" id="xx2" name="lineName" value="choose2">
    <label for="xx2" class="ui-radio"></label>
    <label for="xx2">选项二</label>
</div>

二、原理

设置<input type="radio">状态为透明,设置label.ui-radio为单选按钮默认的样式,给label.ui-radio添加一个伪元素before来模拟出你需要的单选按钮被选中的样子, 并设置visibility: hidden;。当点击单选按钮或者描述文字时通过input:checked伪类选择器来显示被选中的样式。

完整样式:

.check-group {
    display: inline-block;
}
input[type=radio] {
    position: absolute;
    opacity: 0;
    width: 20px;
    height: 20px;
    filter: alpha(opacity=0);
    cursor: pointer;
    z-index: -1;
}

.ui-radio {
    display: inline-block;
    width: 20px;
    height: 20px;
    border: 1px solid rgba(208, 208, 213, 0.99);
    /* IE7-IE8 ignore this */
    border-radius: 50%;
    background-color: #fff;
    box-sizing: border-box;
    vertical-align: -.5ex;
    *vertical-align: 0;
    -webkit-user-select: none;
    -ms-user-select: none;
    user-select: none;
    -webkit-transition: border-color .2s;
    transition: border-color .2s;
    overflow: hidden;
}

:not(:disabled)+.ui-radio:hover {
    border-color: #ababaf;
}

:focus+.ui-radio {
    border-color: rgba(36, 134, 255, 0.99);
}

.ui-radio::before {
    content: '';
    display: block;
    width: 10px;
    height: 10px;
    margin: 4px auto 0;
    border-radius: 50%;
    background-color: #2486ff;
    visibility: hidden;
}

:checked+.ui-radio::before {
    visibility: visible;
}

:disabled+.ui-radio,
.ui-radio.disabled {
    border-color: #ababaf;
    opacity: .38;
}

/* error */
.error.ui-radio {
    border-color: #f4615c;
}

/*IE7, IE8 使用图片作UI*/
@media \0screen\,screen\9 {
    .ui-radio {
        background: url(images/radio.png) no-repeat 0 0;
    }

    .ui-radio:hover {
        background-position: 0 -40px;
    }

    [checked]+.ui-radio {
        background-position: 0 -40px;
    }

    [defaultChecked]+.ui-radio {
        background-position: 0 -40px;
    }

    [checked]+.ui-radio:hover,
    [checked][disabled]+.ui-radio {
        /* disabled态使用高亮边框 */
        background-position: 0 -40px;
    }

    [defaultChecked]+.ui-radio:hover,
    [defaultChecked][disabled]+.ui-radio {
        /* disabled态使用高亮边框 */
        background-position: 0 -40px;
    }

    [disabled]+.ui-radio {
        background-position: 0 -20px;
        filter: alpha(opacity=38);
    }
}

通过js来控制设置input的checked为true或者false

$('.check-group').on('click', function() {
    var that = $(this).children('input');
    var name = that.attr('name');
    $('input[name=' + name + ']').removeAttr('checked');
    that.prop('checked', true);
    that.attr('checked', 'checked');     //ie8一定要加这一句
})

效果:

Chrome/Firefox/Edge/IE9-IE11丝般顺滑
IE8会卡顿(万恶的IE8,哈哈哈哈哈哈)

结语

我平时都是用别的标签来写这种单选按钮的效果的,今天看到一个大神的一篇博客,里面是用的input "type=radio"。 之前也看到同事使用类似的方法,但是他是直接在<input>标签上添加的伪元素:before,但是input是单标签,这样会出现bug。