欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  web前端

CSS秘密花园: 自定义复选框_html/css_WEB-ITnose

程序员文章站 2022-04-30 11:20:40
...
《 CSS Secrets 》是 @Lea Verou 最新著作,这本书讲解了有关于CSS中一些小秘密。是一本CSSer值得一读的一本书,经过一段时间的阅读,我、@南北和@彦子一起将在W3cplus发布一系列相关的读后感,与大家一起分享。

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

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

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

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

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

解决方案

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

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

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

你可能会奇怪有什么其它元素可以让我们使用,并能辨别复选框是否处于选中状态。不错,确实存在一种元素可以围绕复选框有不同的状态:

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

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

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

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

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"] 会隐藏复选框,而且后面不会有一个标签(如,那些嵌入在标签中的),这样会从根本上导致它们无法使用。

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

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

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