supce's blog

CSS Secret 读书笔记之自定义复选框&阴影弱化背景


自定义复选框

单选框和复选框的默认样式确实不敢恭维,但是这两种控件在绝大多数浏览器中仍然无法自由的设置样式。这时候可以用下面这种“曲线救国”的思路来实现自定义复选框。

伪元素解决方案

具体思路如下:
由于label元素可以和复选框关联,起到触发开关的作用。我们可以为它添加伪元素,并基于复选框的状态来为其设置样式。然后再把真正的复选框隐藏起来。

CSS的魅力就在于此,正是label可以和复选框(单选框)关联,才有了自定义复选框的可能性。

有了上面的思路,代码就很简单了。首先是最最最简单的HTML:

<input type="checkbox" id="custom-a" />
<label for="custom-a">自定义复选框</label>

然后给label的伪元素添加一些基本的样式:

body{font:150%/1.5 sans-serif;}
input[type="checkbox"] + label::before{
    content: '\a0'; /*不换行空格*/
    display: inline-block;
    width: .8em;
    height: .8em;
    vertical-align: .1em;
    background: #c00;
    margin-right: .2em;
    border-radius: .3em;
    line-height: .65;
    text-indent: .15em;
}

这时候效果是这个样子的:

下面再给伪元素添加复选框被勾选时的样式:

input[type="checkbox"]:checked + label::before{
    content: '\2713';
    background: yellowgreen;
}

现在就差一步了,就是把原来的复选框以一种不损失可访问性的方式隐层起来。这就意味着我们不能简单粗暴地设置display:none,因为这样会把它从键盘tab键切换焦点的队列中删除。那么怎么隐藏呢,这时候轮到裁剪登场了,可以使用裁剪,将它裁剪掉!

input[type="checkbox"]{
    position: absolute;
    clip: rect(0,0,0,0);
}

然后当伪元素聚焦时再添加box-shadow的特效:

input[type="checkbox"]:focus + label::before{
    box-shadow: 0 0 .1em 2px #58a;
}

OK,完美解决:

当然也可以补充上禁用时的样式:

input[type="checkbox"]:disabled + label::before{
    background: #58a;
    content: '\2713';
    cursor: not-allowed;
}

在上面的例子中,尽量避免把复选框设置为圆形,因为大多数用户会把圆形的选择框理解为单选框。对于单选框则反之。

开关式按钮

利用label的可关联性,也可以用来模拟开关式按钮。开关式按钮与复选框的行为十分相似,可以用来切换某个选项的开关状态:启用时,它是被按下的状态,停用时,它就是浮起的状态。
代码很简单,主要是利用了内嵌阴影的效果。
HTML:

<input type="checkbox" id="switch">
<label for="switch" id="switch-label">开关式按钮</label>

CSS:

#switch[type="checkbox"] + #switch-label{
    display: inline-block;
    padding: .3em .5em;
    background: #ccc;
    background-image: linear-gradient(#ddd,#bbb);
    border: 1px solid rgba(0,0,0,.2);
    border-radius: .3em;
    box-shadow: 0 1px white inset;
    text-shadow: 0 1px 1px white;
}
#switch[type="checkbox"]:checked + #switch-label,
#switch[type="checkbox"]:active + #switch-label{
    box-shadow: .1em .1em .2em rgba(0,0,0,.6) inset;
    border-color: rgba(0,0,0,.4);
    background: #bbb;
}


通过阴影来弱化背景

评论Twitter时,会通过阴影来弱化背景:

主要思路是通过点击事件,给背景设置半透明的背景色,然后将要显示的元素显示出来。这里就要用到js来辅助了。
HTML:

<div class="overlay">
    <p>this is a test this is test click me click me</p>
    <div class="lightbox">this is a light box</div>
</div>

CSS:

.overlay{
    width: 100%;
    height: 10em;
    margin-top: 20px;
    border: 1px solid black;
    /*background-color: rgba(0,0,0,.7);*/
}
.lightbox{
    width: 20em;
    height: 5em;
    margin: auto;
    text-align: center;
    z-index: 1;
    background: white;
    display: none;
}

js:

<script type="text/javascript">
    function $(selector,context){
        context = context || document;
        return context.querySelector(selector);
    }
    function checkDisStyle(obj){
        if(obj.currentStyle){
            return obj.currentStyle.display;
        }else{
            return window.getComputedStyle(obj).display;
        }
    }
    $('.overlay').onclick = function(){
        if (checkDisStyle($('.lightbox')) == 'none') {
            $('.overlay').style.backgroundColor = "rgba(0,0,0,.7)";
            $('.lightbox').style.display = "block";
        }else{
            $('.overlay').style.backgroundColor = "";
            $('.lightbox').style.display = "none";
        }
        // console.log(checkDisStyle($('.lightbox')));
    }
</script> 

搞完手工~

在获取当前样式时,记得兼容IE,使用getComputedStyle方法