高级设计 HTML 表单 - 学习 Web 开发 编辑
在本文中,我们将看到HTML表单怎样使用CSS装饰难以定制的表单小部件。如前面章节所示,文本域和按钮完全可以使用CSS,现在我们将深入探索HTML表单样式。
在继续之前,让我们回忆一下两种表单小部件:
- bad
- 这个元素很难设计,需要一些复杂的技巧,有时还涉及到高级的CSS3的知识。
- ugly
- 忘记使用CSS来设计这些元素吧。你最多能做一点点事情,还不能保证可以跨浏览器,而且在它们出现时永远不能做到完全的受控。
CSS表现力
除了文本框和按钮之外,使用其他表单小部件的主要问题是在许多情况下,CSS的表现不能满足设计复杂的小部件的要求。
HTML和CSS最新的发展扩展了CSS的表现力:
- CSS 2.1 非常受限,只给出三个伪类:
- CSS Selector Level 3 增加了三个与HTML表单相关的伪类:
- CSS Basic UI Level 3 也增加了几个伪类用于描述小部件的状态:
- CSS Selector Level 4 目前处于积极应用和重点讨论的状态,但并不打算为表单做更多的改善:
:user-error
只是改进了伪类:invalid
。
所有这一切是一个好的开端,但是有两个问题。首先,一些浏览器不需要实现CSS 2.1之上的特性。其次在设计像日期选择器这样的复杂的小部件时,这些实在不够好。
浏览器厂家在CSS表现力在表单方面的扩展做了一些尝试,在某些情况下,知道什么可用也挺不错的。
警告: 尽管 这些尝试很有趣,但它们是非标准的,也就是不可靠的。. 如果你使用它们(也许你并不常用),你要自己承担风险,使用非标准的属性对于Web并不是好事 。
控制表单元素的外观
基于WebKit(Chrome, Safari)和 Gecko(Firefox)的浏览器提供更高级的HTML部件定制。它们也实现了跨平台,因此需要一种方式把原生小部件转换为用户可设置样式的小部件。
为此,它们使用了专有属性:-webkit-appearance
或-moz-appearance
。这些属性是非标准的,不应该使用。事实上,它们在WebKit 和Gecko中的表现也是不相同的。然而,有一个值很好用: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 57 (Mac OSX) | |
Firefox 57 (Windows 10) | |
Chrome 63 (Mac OSX) | |
Chrome 63 (Windows 10) | |
Opera 49 (Mac OSX) | |
Internet Explorer 11 (Windows 10) | |
Edge 16 (Windows 10) |
更复杂的例子
由于Opera和Internet Explorer没有像-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;
}
注:下面的内容(仅限样式化 checkbox 部分)与英文版出入极大,猜测已经是过时内容
现在,让我们设计一个定制复选框的样式
计划用自己的图像替换原生的复选框,首先需要准备复选框在所有状态下的图像,那些状态是:未选、已选、禁用不选、禁用已选。该图像将用作CSS精灵:
一开始要隐藏初始复选框。可以简单的把它们从页面视图中拿开。这里要考虑两个重要的事情:
- 不能用
display:none
来隐藏复选框,因为后面我们需要把复选框对用户可见。而使用display:none
,用户不能再访问这个复选框,这就表示复选框不能选择或不选择。 - 我们将使用CSS3选择器来实现定制的样式,为了支持旧版浏览器,可以在所有选择器前设置
:root
伪类。目前所有我们需要支持的浏览器都支持:root
伪类,但是其他的并不能保证。这是一个过滤旧的Internet Explorer的便利方式的例子。那些旧版浏览器将看到传统的复选框,而新式的浏览器可以看到定制的复选框。
:root input[type=checkbox] {
/* original check box are push outside the viexport */
position: absolute;
left: -1000em;
}
现在加上自己的图像就可以摆脱原来的复选框了,为此,要在初始的复选框后面加上<label>
元素,并使用它的:before
伪元素。因此在下面章节中,要使用selector属性来选择复选框,然后使用adjacent sibling selector来选择原有复选框后面的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/wiki/files/4173/checkbox-sprite.png") no-repeat 0 0;
/* The following is used to adjust the position of
the check boxes on the text baseline */
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;
}
你可以在线查看结果:
Dealing with the select nightmare
<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; /* To gain control over the appearance on WebKit/Chromium */
-moz-appearance : none; /* To gain control over the appearance on Gecko */
/* To gain control over the appearance on and Trident (IE)
Note that it also works on Gecko and has partial effects on WebKit */
background : none;
}
Browser | Regular rendering | Tweaked rendering | ||
---|---|---|---|---|
closed | open | closed | open | |
Firefox 57 (Mac OSX) | ||||
Firefox 57 (Windows 10) | ||||
Chrome 63 (Mac OSX) | ||||
Chrome 63 (Windows 10) | ||||
Opera 49 (Mac OSX) | ||||
IE11 (Windows 10) | ||||
Edge 16 (Windows 10) |
如你所见,计时使用了-*-appearance
属性的帮助,任然有一些遗留的问题:
- 不同的操作系统和浏览器对属性
padding
属性的处理各不相同。 - Internet Explorer旧版本不允许平滑样式
- Firefox没有实现下拉箭头的样式。
- 如果要在下拉列表内实现
<option>
元素样式,Chrome和Opera浏览器的表现在不同的系统中是不一样的。
在我们的例子中,只使用了三个CSS属性,在考虑使用更多CSS属性时,可以想象是很混乱的。正如我们看到的,CSS始终不适合用来修改这些小部件的外观,但是仍然可以用来稍微做一些事情。如果愿意的话,可以演示一下在不同操作系统和浏览器之间的区别。
我们也可以帮助了解在下一章节中哪个属性更合适:Properties compatibility table for form widgets
走向更完美表单之路:有用的库和polyfills(腻子)
虽然对于复选框和单选按钮而言,CSS的表示方式足够丰富,但是对更高级的小部件来说差距仍然很大。即使可以用<select>
元素作一些事情,但是对file小部件的样式完全没用。对于日期选择器也同样如此。
要实现对表单小部件的完全控制,你别无选择,只能选择依靠JavaScript。在文章How to build custom form widgets中,我们将看到具体的做法,其中还有一些非常有用的库:
- Uni-form是一个对采用CSS样式的表单标记实现标准化的框架,在使用jQuery时,还提供一些附加特性,但这是可选的。
- Formalize是对公共JavaScript框架的扩展(如jQuery, Dojo, YUI等),有助于规范和定制表单。
- Niceforms是一个独立的JavaScript方法,能提供web表单的完整定制。
下面的库不止应用于表单,他们在处理HTML表单时是非常有趣的:
- jQuery UI做了一些有趣的改进,可以定制象日期选择器(特别关注可访问性)这样的小部件。
- Twitter Bootstrap在规范表单时是非常有用的。
- WebShim是一个大型工具,可以用来处理浏览器对HTML5的支持。对web表单部分确实有用。
记住,使用CSS和JavaScript是有副作用的。所以在选择使用那些库时,应该在脚本失败的情况下能回滚样式表。脚本失败的原因很多,尤其在手机应用中,因此你需要尽可能好的设计你的Web站点或应用。
相关链接
虽然HTML表单使用CSS仍有一些黑洞,但通常也有方法绕过它们。即使没有清楚的,通用的解决方案,但新式的浏览器也提供了新的可能性。目前最好的方法是更多的学习不同浏览器支持CSS的方式,并应用于HTML表单小部件。
在本指南的下一章节中,我们将探讨不同的HTML表单小部件怎样很好的支持更重要的CSS属性:Properties compatibility table for form widgets.
相关链接
上一页 Overview: Forms 下一页在本单元中
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论