【譯】HTML表單高級樣式

在本文中,咱們將瞭解如何在HTML表單上使用CSS,爲那些難於自定義的表單組件加以樣式。如前文所述,文本框和按鈕很適合使用CSS,而如今咱們得來探索HTML表單樣式的那些坑了。html5

在進一步討論前,先回顧下兩種HTML表單組件:css3

比較糟糕的
一些元素只能使用不多的樣式,並且得依賴一些複雜的技巧,偶爾還得用到CSS3的高級知識。git

醜陋的
別期望用CSS給這些元素添加樣式了。在最好的狀況,你還能寫一點不能跨瀏覽器支持的代碼,並且還不可能徹底控制這些元素的樣式。github

CSS的表現力

除了文本框和按鈕,表單組件面臨的最大問題,是CSS在多數狀況下沒有足夠的表現力來恰當地給複雜組件添加樣式。web

近來HTML和CSS的演進已在拓展CSS的表現力:bootstrap

雖然上述這些都是個好的開始,但其中仍有兩個問題:第一,某些瀏覽器並不會實現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屬性的支持程度:[表單組件的屬性兼容表]()。

參見

相關文章
相關標籤/搜索