【译】HTML表单高级样式
在本文中,我们将了解如何在HTML表单上使用CSS,为那些难于自定义的表单组件加以样式。如前文所述,文本框和按钮很适合使用CSS,而现在我们得来探索HTML表单样式的那些坑了。
在进一步讨论前,先回顾下两种HTML表单组件:
比较糟糕的
一些元素只能使用很少的样式,而且得依赖一些复杂的技巧,偶尔还得用到CSS3的高级知识。
丑陋的
别指望用CSS给这些元素添加样式了。在最好的情况,你还能写一点不能跨浏览器支持的代码,而且还不可能完全控制这些元素的样式。
CSS的表现力
除了文本框和按钮,表单组件面临的最大问题,是CSS在多数情况下没有足够的表现力来恰当地给复杂组件添加样式。
近来HTML和CSS的演进已在拓展CSS的表现力:
CSS2.1很受限,只提供了三个伪类:
CSS Selector Level 3新增了几个和HTML表单相关的伪类:
CSS Basic UI Level 3也添加了几个伪类用于描述组件状态:
CSS Selector Level 4正处于开发状态,而且讨论的重点并不在于增加更多内容以改进表单:
:user-error只是
:invalid
伪类的一个增强版、
虽然上述这些都是个好的开始,但其中仍有两个问题:第一,某些浏览器并不会实现CSS2.1之外的特性。第二,这些改进并未好到能处理诸如日期选择器之类的复杂组件。
浏览器厂商也为拓展CSS在表单上的表现力做了些试验,最好得了解下哪些可以使用。
警告:虽然这些实验挺有趣的,但它们并非标准、并不可靠。若你要使用它们(通常你也不会这么做),你得自己担起风险,而且使用非标准属性也是可能阻碍Web发展的做法。
控制表单元素的外观
基于 WebKit- (Chrome, Safari) 和 Gecko- (Firefox) 的浏览器为HTML组件提供了最高等级的定制。这些定制也是跨平台的,所以浏览器需要一个机制来转换那些能被改变样式的表单组件的原生外观和体验。
于是它们使用了私有属性:-webkit-appearance 或 -moz-appearance。这些属性是非标准的,也不应被使用。实际上,它们在Webkit和Gecko上的表现也不尽相同。但是,有一个值是应该知道的:none
,使用该值你就可以获得对组件样式的(几乎所有)控制权。
所以,若你在一个元素上应用样式时遇到问题,可以试着使用这些私有属性(译注:用none
值覆盖默认值)。下面我们会看到几个例子,但最为人熟知的用例是重置Webkit浏览器上搜索框的样式。
<form>
<input type="search">
</form>
<style>
input[type=search] {
border: 1px dotted #999;
border-radius: 0;
-webkit-appearance: none;
}
</style>
注意:在我们讨论Web技术时,是难于预测未来的,但拓展CSS的表现力确实很难。另一些做了探索工作的标准如Shadow DOM提供了新的视角。我们对完全可配置样式的表单的追求还远未结束。
示例
多选框和单选框
给多选框和单选框添加样式是很让人凌乱的。例如,多选框和单选框的大小往往不会发生改变,而且不同浏览器的表现相当不同。
一个简单例子
考虑如下示例:
<span><input type="checkbox"></span>
span {
display: inline-block;
background: red;
}
input[type=checkbox] {
width : 100px;
height: 100px;
}
不同浏览器的处理如下:
浏览器 | 渲染效果 |
---|---|
Firefox 16 (Mac OSX) | |
Chrome 22 (Mac OSX) | |
Opera 12.01 (Mac OSX) | |
Internet Explorer 9 (Windows 7) | |
Internet Explorer 7 (Windows XP) |
复杂点的例子
由于Opera和IE没有诸如-webkit-appearance
和-moz-appearance
之类的特性,所以使用这类特性是不太合适的。幸运的是,在这种情况下用CSS还能找出解决办法来。举一个常见的例子:
<form>
<fieldset>
<p>
<input type="checkbox" id="first" name="fruit-1" value="cherry">
<label for="first">I like cherry</label>
</p>
<p>
<input type="checkbox" id="second" name="fruit-2" value="banana" disabled>
<label for="second">I can't like banana</label>
</p>
<p>
<input type="checkbox" id="third" name="fruit-3" value="strawberry">
<label for="third">I like strawberry</label>
</p>
</fieldset>
</form>
加一些基本样式:
body {
font: 1em sans-serif;
}
form {
display: inline-block;
padding: 0;
margin : 0;
}
fieldset {
border : 1px solid #CCC;
border-radius: 5px;
margin : 0;
padding: 1em;
}
label {
cursor : pointer;
}
p {
margin : 0;
}
p+p {
margin : .5em 0 0;
}
现在,我们来加样式以获得一个定制的复选框。
我们的计划是用我们自己的图像来替换原生的复选框。首先得准备一张具有所有复选框所需状态的图像,这些状态有:未勾选、已勾选、禁用未勾选、禁用已勾选。该图像可用CSS雪碧图来做:
先从隐藏原生的复选框开始,我们只是简单地把它们从页面的可视范围中挪出。这里有两个要重点考虑的事:
别使用
display:none
来隐藏复选框,因为如前面提到的,我们需要保证复选框对用户可用。使用display:none
的话,复选框就不再是用户可访问的,即不能再勾选或者不勾选它。我们将使用一些CSS3选择器来实现我们的样式。为支持老旧浏览器,可以在我们要用的选择器前加:root伪类。在已有的实现中,支持我们需要的选择器的浏览器也支持
:root
伪类,而剩下的浏览器就不支持了。所以这是一种用来识别老旧浏览器的方便做法,老旧浏览器中将会看到普通的复选框、而现代浏览器中将会看到定制的复选框。
:root input[type=checkbox] {
/* 原生的复选框会从页面的可视范围中被挪出 */
position: absolute;
left: -1000em;
}
现在我们已经移除了原生的复选框,可以添加我们自己的了,这里会在原生复选框后面的<label>
元素使用:before伪元素。下面的选择器中,我们先用属性选择器来获取复选框;然后使用相邻兄弟选择器来获取原来复选框后的label
。最后我们通过给:before
伪元素添加样式,用其来显示我们定制的复选框。
:root input[type=checkbox] + label:before {
content: "";
display: inline-block;
width : 16px;
height : 16px;
margin : 0 .5em 0 0;
background: url("https://developer.mozilla.org/files/4173/checkbox-sprite.png") no-repeat 0 0;
/* 下一属性用于在文本基线调整复选框的位置 */
vertical-align: bottom;
position: relative;
bottom: 2px;
}
接下来用原来复选框的:checked和:disabled伪类来改变我们定制的复选框的状态。由于我们使用了CSS雪碧图,我们只需要调整背景的位置而已。
:root input[type=checkbox]:checked + label:before {
background-position: 0 -16px;
}
:root input[type=checkbox]:disabled + label:before {
background-position: 0 -32px;
}
:root input[type=checkbox]:checked:disabled + label:before {
background-position: 0 -48px;
}
最后也是很重要的一步:当用户使用键盘在不同表单组件间浏览时,每个组件应该能看到聚焦的效果。由于我们隐藏了原生的复选框,所以只能自己实现这一特性来让用户知晓他们正处于何处。下列的CSS实现了对我们的定制复选框的聚焦:
:root input[type=checkbox]:focus + label:before {
outline: 1px dotted black;
}
最终效果如下:
处理选择框噩梦
<select>
元素被认为是一个“丑陋的”组件,因为不太可能给它添加跨平台的样式。当然,还是有一些可以探讨的东西的,这里就不长篇大论了,先看个例子:
<select>
<option>Cherry</option>
<option>Banana</option>
<option>Strawberry</option>
</select>
select {
width : 80px;
padding : 10px;
}
option {
padding : 5px;
color : red;
}
后面的表格展示了不同浏览器如何在两种情况下处理这一样式。(渲染效果中)前两列只是简单的例子,后两列则使用了些定制的CSS来获得对组件外观的更多控制,如下所示:
select, option {
-webkit-appearance : none; /* 获得对Webkit浏览器里外观的控制 */
-moz-appearance : none; /* 获得对Gecko浏览器里外观的控制 */
/* 获得对Presto (Opera) 和 Trident (IE)浏览器里外观的控制
注意这也能在Gecko浏览器里起作用,且对Webkit浏览器有副作用 */
background : none;
}
浏览器 | 普通渲染(关闭) | 普通渲染(打开) | 调整后渲染(关闭) | 调整后渲染(打开) |
---|---|---|---|---|
Firefox 16 (Mac OSX) | ||||
Firefox 16 (Windows 7) | ||||
Chrome 22 (Mac OSX) | ||||
Chrome 22 (Windows 7) | ||||
Opera 12.01 (Mac OSX) | ||||
Internet Explorer 9 (Windows 7) | N/A | N/A | ||
Internet Explorer 7 (Windows XP) | N/A | N/A |
如你所见,即使使用了 -*-qppearance
属性,仍会有问题存在:
padding属性在不同操作系统和浏览器中的处理是不一致的。
老旧的IE不支持平滑的样式。
火狐没有能给予下拉箭头样式的方式。
若想要给下拉菜单中的
<option>
元素以样式,则Chrome和Opera在不同系统下的表现不尽相同。
同时,在本例中,我们只讨论了三个CSS属性;想想要考虑更多的CSS属性会有多么混乱。可见,CSS确实不太适合用来改变这些组件的外观和体验,但它仍让你能做些调整,如果你愿意忍受不同浏览器或不同操作系统上的不同的话。
我们将在下篇文章:[表单组件的属性兼容表]()中尝试指出哪些属性是可用的。
通向漂亮表单之路:一些有用的库和拓展工具
尽管CSS在复选框和单选框上的表现力已经够用了,但离其支持高级表单组件仍然遥遥无期。即使在<select>
元素上有一些可能,但文件组件、日期选择器等仍不能被添加样式。
若你想获得对表单组件的完整控制权,你就得依赖Javascript,别无选择。在[怎样创建定制表单组件]()一文中,我们将了解如何自己实现它,而如今有一些很有用的库可以帮到你:
Uni-form是一个规范了表单格式和使用CSS给予表单样式的框架。在和jQuery一起使用时,它也提供了些额外的可选特性。
Formalize是一些常见Javascript框架(如jQuery、Dojo、YUI等)的一个插件,用于规范化和定制表单。
Niceforms是个提供了完整web表单定制的独立Javascript方法。你可以使用一些内建的主题、也可自己创建。
下面几个库则不止用于处理表单,但它们在处理HTML表单时有很多有趣的特性:
jQuery UI提供了些非常有趣的可定制高级组件,比如日期选择器(特别关注了无障碍访问)。
Twitter Bootstrap非常有用,如果你想规范化你的表单的话。
WebShim是一个庞大的工具,用于处理那些支持HTML5的浏览器。其web表单部分挺有用的。
要知道,绑定CSS和Javascript会引起副作用。所以若你选择了上述的一种库,就得时常保证在脚本失效时会可回退的样式表。造成脚本失效的原因很多,特别在移动端,故你的Web站点或app设计得能最好地处理这些情况。
结论
当在HTML表单上使用CSS仍存在许多坑时,有很多方法可以绕过这些坑。本来是没有确切、通用的解决方案的,但现代浏览器带来了新可能。而现在,最佳方案是研究不同浏览器对用在HTML表单组件的CSS的支持程度。
下篇文章,我们将探索各种HTML表单组件对那些最重要的CSS属性的支持程度:[表单组件的属性兼容表]()。
参见
【译】HTML表单高级样式的更多相关文章
- HTML表单 CSS样式
1.HTML表单 <body rightmargin="50" leftmargin="50" background="未标题-1.jpg&qu ...
- css修改input表单默认样式重置与自定义大全
链接地址: 伪元素表单控件默认样式重置与自定义大全 http://www.zhangxinxu.com/wordpress/?p=3381 Chrome 现在不支持通过伪元素修改 meter 元素样式 ...
- BootStrap的table表格,栅格系统,form表单的样式
BootStrap BootStrap的简介 1. 什么是Bootstrap 由两个前端设计师开发的一个前端的框架(Html,css,js) 简化了程序员写css的代码 2. 为什么使用B ...
- ios下表单disabled样式重置
在做最近的一个活动项目时,需要用到表单的disabled状态,但是在IOS下那颜色不是一般的浅,就跟没有一样,一开始通过如下样式重置: input:disabled, input[disabled]{ ...
- validform.js+layer.js 表单验证样式
$("#formAdd").Validform({ tiptype: function (msg, o, cssctl) { if (o.type == 3) {//失败 laye ...
- Bootstrap表单布局样式
1.并排和下拉选项 <form class="form-horizontal" role="form"> <fieldset> < ...
- 推荐的bootstrap之 formgroup表单布局样式
一直没能找到比较好的Form Group样式,直到找到如下样式 转自 https://www.cnblogs.com/jokerjason/p/5721349.html <form class= ...
- [moka同学笔记]yii表单dropdownlist样式
<?= $form->field($modelUser,'name') ?> <div class="form-group field-community-mobil ...
- Yii2 ActiveForm表单自定义样式
实例: <?php $form = ActiveForm::begin([ 'fieldConfig' => [ 'template' => '<div class=" ...
随机推荐
- Java 实现Https访问工具类 跳过ssl证书验证
不多BB ,代码直接粘贴可用 import java.io.BufferedReader; import java.io.ByteArrayOutputStream; import java.io.F ...
- linux多进/线程编程(2)—— fork函数和进程间“共享”数据
参考: 1.博客1:https://www.pianshen.com/article/4305691855/ fork:在原进程的基础上"分叉"出一个子进程,即创建一个子进程. N ...
- Java应用层数据链路追踪(附优雅打印日志姿势)
我是3y,一年CRUD经验用十年的markdown程序员常年被誉为优质八股文选手 今天来聊些大家都用得上的东西:数据链路追踪.之前引入了系统的监控来快速定位应用操作系统上的问题,而业务问题呢?在这篇 ...
- Linux下配置远程免密登录
第一步: 输入ssh-keygen: [root@localhost zookeeper-3.5.7]# ssh-keygen Generating public/private rsa key pa ...
- 二进制部署1.23.4版本k8s集群-1-系统安装及环境准备
1. 致谢 这篇文章参考了老男孩王导的视频,在此表示感谢和致敬! 2. 安装CentOS操作系统 系统镜像:CentOS-7-x86_64-DVD-2009.iso 安装过程略. 3. 环境准备 3. ...
- 微信小程序实现图表展示
开发可参考以下链接 点击有道云链接 小程序柱状图展示 [单元目标] 掌握小程序柱状图展示 [教学内容] 1.1 掌握组件导入 在miniprogram下的utils文件夹(若没有就新建一个)下,新建w ...
- php 23种设计模型 - 抽象工厂模式
抽象工厂模式(AbstractFactory) 抽象工厂模式(Abstract Factory Pattern)是围绕一个超级工厂创建其他工厂.该超级工厂又称为其他工厂的工厂.这种类型的设计模式属于创 ...
- 『现学现忘』Docker基础 — 23、使用Docker安装Tomcat
目录 步骤1:搜索镜像 步骤2:下载Tomcat镜像 步骤3:运行Tomcat镜像 步骤4:本机和外网测试 步骤5:解决问题 补充:--rm选项 步骤1:搜索镜像 使用docker search命令进 ...
- web自动化之selenium(四)元素等待
隐式等待 说明 隐式等待是通过设置一定时长的等待,让页面上的某些元素能过加载出来,如果超过了设置的时间还没有加载出来则抛出(NoSuchelementException异常),默认单位为"秒 ...
- SpringCloud微服务之Ribbon负载均衡(一)
什么是微服务?什么是SpringCloud? 微服务是一种架构的模式,它提倡将一个应用程序划分成很多个微小的服务,服务与服务之间相互协调.相互配合.每个服务运行都是一个独立的进程,服务与服务之间采用轻 ...