--- title: 高级设计 HTML 表单 slug: Learn/Forms/Advanced_form_styling translation_of: Learn/Forms/Advanced_form_styling original_slug: Learn/HTML/Forms/Advanced_styling_for_HTML_forms ---
在本文中,我们将看到HTML表单怎样使用CSS装饰难以定制的表单小部件。如前面章节所示,文本域和按钮完全可以使用CSS,现在我们将深入探索HTML表单样式。
在继续之前,让我们回忆一下两种表单小部件:
除了文本框和按钮之外,使用其他表单小部件的主要问题是在许多情况下,CSS的表现不能满足设计复杂的小部件的要求。
HTML和CSS最新的发展扩展了CSS的表现力:
所有这一切是一个好的开端,但是有两个问题。首先,一些浏览器不需要实现CSS 2.1之上的特性。其次在设计像日期选择器这样的复杂的小部件时,这些实在不够好。
浏览器厂家在CSS表现力在表单方面的扩展做了一些尝试,在某些情况下,知道什么可用也挺不错的。
警告: 尽管 这些尝试很有趣,但它们是非标准的,也就是不可靠的。. 如果你使用它们(也许你并不常用),你要自己承担风险,使用非标准的属性对于Web并不是好事 。
基于WebKit(Chrome, Safari)和 Gecko(Firefox)的浏览器提供更高级的HTML部件定制。它们也实现了跨平台,因此需要一种方式把原生小部件转换为用户可设置样式的小部件。
为此,它们使用了专有属性:{{cssxref("-webkit-appearance")}}或{{cssxref("-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>
{{EmbedLiveSample("Controlling_the_appearance_of_form_elements", 250, 40)}}
注意:当我们谈及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没有像{{cssxref("-webkit-appearance")}}或{{cssxref("-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
,用户不能再访问这个复选框,这就表示复选框不能选择或不选择。:root input[type=checkbox] { /* original check box are push outside the viexport */ position: absolute; left: -1000em; }
现在加上自己的图像就可以摆脱原来的复选框了,为此,要在初始的复选框后面加上{{HTMLElement("label")}}元素,并使用它的{{cssxref(":before")}}伪元素。因此在下面章节中,要使用selector属性来选择复选框,然后使用adjacent sibling selector来选择原有复选框后面的label
。最后,访问{{cssxref(":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; /* The following is used to adjust the position of the check boxes on the text baseline */ vertical-align: bottom; position: relative; bottom: 2px; }
在初始复选框上使用{{cssxref(":checked")}}和{{cssxref(":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; }
你可以在线查看结果:
{{EmbedLiveSample("A_more_complex_example", 250, 130)}}
{{HTMLElement("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
属性的帮助,任然有一些遗留的问题:
在我们的例子中,只使用了三个CSS属性,在考虑使用更多CSS属性时,可以想象是很混乱的。正如我们看到的,CSS始终不适合用来修改这些小部件的外观,但是仍然可以用来稍微做一些事情。如果愿意的话,可以演示一下在不同操作系统和浏览器之间的区别。
我们也可以帮助了解在下一章节中哪个属性更合适:Properties compatibility table for form widgets
虽然对于复选框和单选按钮而言,CSS的表示方式足够丰富,但是对更高级的小部件来说差距仍然很大。即使可以用{{HTMLElement("select")}}元素作一些事情,但是对file小部件的样式完全没用。对于日期选择器也同样如此。
要实现对表单小部件的完全控制,你别无选择,只能选择依靠JavaScript。在文章How to build custom form widgets中,我们将看到具体的做法,其中还有一些非常有用的库:
下面的库不止应用于表单,他们在处理HTML表单时是非常有趣的:
记住,使用CSS和JavaScript是有副作用的。所以在选择使用那些库时,应该在脚本失败的情况下能回滚样式表。脚本失败的原因很多,尤其在手机应用中,因此你需要尽可能好的设计你的Web站点或应用。
虽然HTML表单使用CSS仍有一些黑洞,但通常也有方法绕过它们。即使没有清楚的,通用的解决方案,但新式的浏览器也提供了新的可能性。目前最好的方法是更多的学习不同浏览器支持CSS的方式,并应用于HTML表单小部件。
在本指南的下一章节中,我们将探讨不同的HTML表单小部件怎样很好的支持更重要的CSS属性:Properties compatibility table for form widgets.
{{PreviousMenuNext("Learn/HTML/Forms/Styling_HTML_forms", "Learn/HTML/Forms/Property_compatibility_table_for_form_widgets", "Learn/HTML/Forms")}}