现代 CSS

CSS秘密花园: 自定义复选框

特别声明:如果您喜欢小站的内容,可以点击申请会员进行全站阅读。如果您对付费阅读有任何建议或想法,欢迎发送邮件至: airenliao@gmail.com!或添加QQ:874472854(^_^)

CSS Secrets》是@Lea Verou最新著作,这本书讲解了有关于CSS中一些小秘密。是一本CSSer值得一读的一本书,经过一段时间的阅读,我、@南北@彦子一起将在W3cplus发布一系列相关的读后感,与大家一起分享。

CSS Secrets

设计师总是希望能够对Web页面上的每个元素都能有更多的控制。当一个CSS经验有限的图形设计师需要创建一个网站案例时,他们很喜欢自定义表单元素,然后让开发人员来把它转变成CSS。

对于可读性,在这一整节中,我们都会使用“checkbox”,但是讨论的内容都适用于复选框和单选按钮,除非有特别说明。

在CSS刚开始引入的时候,表单样式是非常有限的,而且没有在任何的各种CSS规范中明确定义。但是,浏览器对CSS属性越来越宽松,它们允许表单控制,可以让我们有相当大的空间去给它们添加样式。

可惜的是,复选框和单选按钮不在可控制的表单控件列表中。现在,大多数浏览器基本都是选择不给它们添加样式。结果是,作者要么使用默认外观,要么使用繁琐的标签来完成,如使用div和JavaScript来重建它们。

有没有什么办法可以让我们摆脱这些限制,然后自定义我们的复选框样式呢,不要那些臃肿的代码,不要放弃语义性和可访问性?

解决方案

直到几年前,如果不用脚本,这个任务基本是不可能完成的。但是,在CSS3中,我们有了一个新的伪类::checked。这个伪类只能在复选框被选中时匹配,无论这个选中状态是通过用户交互还是脚本实现的。

:checked和属性选择器[checked]之间有什么不同吗?后者不会基于用户交互更新,因为用户交互不会影响HTML属性。

如果是直接应用于复选框的话并不是特别有用,如——像我们前面提到的——没有多少属性可以让我们成功地给它们应用样式。但是,我们根据复选框的状态,给其它元素添加样式,并把它们组合起来。

你可能会奇怪有什么其它元素可以让我们使用,并能辨别复选框是否处于选中状态。不错,确实存在一种元素可以围绕复选框有不同的状态:<label>。一个<label>可以和复选框的状态相联系,可以作为复选框状态的一个开关。

因为标签——不像复选框——不是替换元素,我们可以为它们添加生成的内容,还可以基于复选框的状态给它们应用不同的样式。然后,我们通过某种方式隐藏真正的复选框,但是不从tab键的切换中将其删除,然后将生成的内容伪装成是经过添加样式的复选框!

将复选框嵌入标签中可以让我们从使用id中解放,但随后,我们就不能根据复选框的状态来选中标签了,因为我们还没有父选择器。

我们来实践一下。我们可以从下面这个简单的示例开始:

<input type="checkbox" id="awesome" />
<label for="awesome">Awesome!</label>

下一步是生成一个伪元素,伪装成我们已添加样式的复选框,并为它应用如下的基本样式:

input[type="checkbox"] + label::before {
    content: '\a0'; /* non-break space */
    display: inline-block;
    vertical-align: .2em;
    width: .8em;
    height: .8em;
    margin-right: .2em;
    border-radius: .2em;
    background: silver;
    text-indent: .15em;
    line-height: .65;
}

你可以在下图中看到我们的复选框和标签的当前样式。

自定义复选框

初始的复选框仍然是可见的,但是我们会在后边把它隐藏掉。现在我们需要给选中状态的复选框应用一个不同的样式。可以简单地应用一个不同的颜色,并添加一个如下的复选标记:

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

我们将应用于我们复选框的样式在这些示例中是非常基础的,但是可能性是无穷的!你甚至可以完全跳过CSS样式,然后使用图片表示不同的复选框状态!

自定义复选框

如上图所示,这已经是一个具有初步样式的复选框。现在我们需要通过一个可访问的方式隐藏初始的复选框,这也就意味着我们不可以使用display: none,因为这样的话就会把它从整个tab键顺序中删掉了。所以,我们可以使用如下的代码:

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

使用这种宽松的选择器时要小心。使用input[type="checkbox"]会隐藏复选框,而且后面不会有一个标签(如,那些嵌入在标签中的),这样会从根本上导致它们无法使用。

就是它了,我们已经做出了一个很基本的自定义复选框!当然我们还可以再做一些提升——比如,在它处于focuseddisabled的状态时改变一下样式:

input[type="checkbox"]:focus + label::before {
    box-shadow: 0 0 .1em .1em #58a;
}
input[type="checkbox"]:disabled + label::before {
    background: gray;
    box-shadow: none;
    color: #555;
}

效果如下图所示:

自定义复选框

从上到下:自定义focus状态的复选框,自定义disabled状态的复选框,checked状态的复选框

你甚至可以通过应用过渡或动画或弹跳让这些效果更平滑,然后创建像sekuomorphic开关这样的东西,可能性是无穷无尽的!

尽管可能是无穷的,也切记不要把复选框变成圆形:很多用户会把它当成单选按钮。正方形单选按钮也是一样。

Ryan Seddon创建了这个效果的第一个版本,他现在被称为“the checkbox hack”。Ryan使用这个方法实现了很多可以切换状态的小部件,如模拟对话框,下拉菜单,选项卡,轮播图等,虽然滥用复选框也导致了可访问性的问题。

开关按钮

你可以使用不同的“the checkbox hack”来模拟开关按钮,因为HTML没有提供一个native的方式来创建它们。开关按钮就是像复选框那样拨动开关:它们用来将某个设置打开或关闭,在选中状态时看起来像是按下的,在未选中状态时看起来就像是没有按下的。从语义上讲,开关按钮和复选框之间并没有真正的区别,所以你都可以使用这些技巧并保持语义纯度。

为了使用这些技巧创建开关按钮,你只需要把标签弄成按钮那样的样式,而不是使用伪元素。例如,创建如图所示的开关按钮

自定义复选框

代码如下:

input[type="checkbox"] {
    position: absolute;
    clip: rect(0,0,0,0);
}
input[type="checkbox"] + 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-align: center;
    text-shadow: 0 1px 1px white;
}
input[type="checkbox"]:checked + label,
input[type="checkbox"]:active + label {
    box-shadow: .05em .1em .2em rgba(0,0,0,.6) inset;
    border-color: rgba(0,0,0,.3);
    background: #bbb;
}

所以,要谨慎使用开关按钮。在大多数情况下,开关按钮会妨碍可用性,因为它们会很容易地与普通按钮被按下时将执行的操作相混淆。

如需转载,烦请注明出处:http://www.w3cplus.com/css3/css-secrets/custom-checkboxes.htmlAir Jordan I Mid

返回顶部