基於vertical-align的表單元素垂直對齊方式研究 By 小強 @ 2009年10月27日 [ 前端表現 ]

原文地址:http://blog.chinaunix.net/uid-26615074-id-3078537.html


最近的項目涉及到很多表單的製作,特別是複選框(checkbox)和單選框(radio)。但是在前端開發過程中發現,單(復)選框和它們後面的提示文字在不進行任何設置的情況下,是無法對齊的,而且在Firefox和IE中相差甚大。即使設置了vertical-align:middle,也依然不能完美對齊。

如下圖所示:

liuhanyu-1

於是上網查看了一些網站,發現這個問題是普遍存在的,如下圖(FF3.5):

error

在很多網站涉及到表單的頁面中,都存在這種表單元素與提示文字無法對齊的問題。於是打算研究一下這個問題。首先,搜索到了藍色上wheatlee前輩的文章《大家都對vertical-align的各說各話》。wheatlee在他的文章中關於垂直居中提到了這樣幾個關鍵點:

1、vertical-align:middle的時候,是該元素的中心對齊周圍元素的中心。

2、這裏“中心”的定義是:圖片當然就是height的一半的位置,而文字應該是基於baseline往上移動0.5ex,亦即小寫字母“x”的正中心。但是很多瀏覽器往往把ex這個單位定義爲0.5em,以至於其實不一定是x的正中心

(baseline等名詞如果不懂,請先閱讀wheatlee的文章)

按照這個思路,對照我遇到的問題,首先想到的是先驗證一下瀏覽器對於“複選框”和圖片是不是使用同樣的規則來渲染(是不是把複選框當成一個正方形圖片來對待)。於是寫出下面的代碼:

<style>
body{font-size:12px;}
</style>

<input style=”vertical-align:middle;” name=”test” type=”checkbox”>
<img style=”vertical-align:middle;”  src=”testpic.gif” />
測試文字

代碼中的testpic.gif是一個尺寸與複選框完全一樣的黑色圖片。FF3.5下顯示如下:

02

事實證明,FF3.5對於複選框和圖片的垂直對齊方式是採用同樣的規則進行渲染的,即將複選框當作一個正方形的圖片(IE不是)。按照wheatlee“middle的時候,是該元素的中心對齊周圍元素的 中心”的觀點,如果我在複選框後面輸入英文字符,那麼複選框的中心將與英文中小寫字母x的中心對齊。經測試,FF3.5下面基本上是這樣的(在一些字號的 時候會有一定的誤差,比如,如果字體高度是偶數,那麼這個中心點有時在一半偏上1px,有時在一半偏下1px)。如圖:

03

但是這對於中文來說,並不是一個好的結果。因爲中文是方塊字,並且相同字號的情況下,高度會比小寫的x高出很多。所以,按照瀏覽器內置的方式,只用 vertical-align:middle是無論如何也無法對齊中文的(無論是隻寫中文,中文在前,英文在前,FF3.5都是按照小寫x中心那種方法來 對齊的。)。但是回頭再看看wheatlee的文章,他說這個小寫x中心對齊的渲染方式,是對於“文字”來說的。那麼,如果不是文字呢…?如果複選框後面 跟的是一個行內元素,如label,而文字是寫在它內部的,會是什麼樣呢?瀏覽器會不會將這個內聯元素整體看作一個“塊”,然後依照類似圖片的規則進行渲 染呢?如果那樣,我們就達到目的了。

但是經過測試,很遺憾,事實並不是這樣,加上label後跟沒加沒有任何區別。FF3.5/IE6/IE7均是如此。在FF3.5中用firebug看一下,證明瀏覽器並沒有按照label的高度值來去對齊中心點。如圖:

04

如果按照之前的設想,紅藍兩線應該是重合的。但現在的情況是,它們相差了1px。並且這1px是沒有規律的,隨着字號的放大,並不恆定,貌似輕易也無法提煉出對應關係來。於是想到,再試一下將label也加上vertical-align:middle。結果如圖:

05

在FF3.5和IE7下面已經很接近於我們希望的狀態了,只差1px。IE6下… 無語了。

經過以上折騰,我得出了跟wheatlee相同的結論,就是,各種瀏覽器之間對這個問題的處理貌似沒有任何規律。並且,似乎每一種瀏覽器對於 vertical-align:middle的渲染都不是完全遵從W3C所說的“Align the vertical midpoint of the box with the baseline of the parent box plus half the x-height of the parent.”

但是經過仔細總結和分析,發現好像最終對齊的結果跟label的高度當前字體中小寫x的中心點都有關係,兩者同時影響着渲染結果。那麼,既然現在的情況以及非常接近於希望的狀態了,是否可以通過設置字體的方式來改變小寫x的中心點的位置,接入對垂直對齊結果進行“微調”呢?

最終,在不斷的測試中發現,如果將font-family中的第一個字體設置爲Tahoma,則可以完美的實現對齊(Verdana等字體也可以)。而且在FF3.5/IE6/IE7/IE8和Chrome中均顯示正常。最終代碼如下:

<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN” “http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd”>
<html xmlns=”http://www.w3.org/1999/xhtml”>
<head>
<meta http-equiv=”Content-Type” content=”text/html; charset=UTF-8″ />
<title>測試vertical-align</title>
<style>
label{vertical-align:middle}
.inputcheckbox{vertical-align:middle;}
body{font-family:tahoma;font-size:12px;}
</style>
</head>
<body>
<input class=”inputcheckbox” name=”test” value=”1″ type=”checkbox”>
<label>測試文字x</label>
</html>

最終效果:

06

至此,多選框(checkbox)和提示文字對齊的問題已經解決,那麼其他表單元素呢?試驗了一下單選框(radio),發現,還是有問題。文字提示依然 是偏上。用firebug看了一下,發現radio元素默認有5px的左邊距和3px的上、右邊距,卻沒有下邊距。如圖:

08

於是,嘗試去掉radio的外邊距,刷新後顯示正常。(其實多選框也是有外邊距的,只是它的外邊距四個方向都有,並且相等,所以對於垂直對齊沒有影響。) 下圖是一些常用表單元素的最終顯示效果以及最終代碼,大家可以用不同瀏覽器看一下實際的效果(注:由於演示使用的12px的中文實際只有11px高,而 IE下文本框等元素的高度是22px,一個是奇數,一個是偶數,所以這些部分在IE中是無論如何也對不齊的,差1px。如果手動控制文本框高度爲奇數,或 者將文字設置成爲偶數的高度,則顯示正常):

09

<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN” “http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd”>
<html xmlns=”http://www.w3.org/1999/xhtml”>
<head>
<meta http-equiv=”Content-Type” content=”text/html; charset=UTF-8″ />
<title>測試vertical-align</title>
<style>
*{margin:0;}
label{vertical-align:middle}
.inputcheckbox{vertical-align:middle;}
body{font-family:tahoma;font-size:12px;}
</style>
</head>
<body>
<input class=”inputcheckbox” name=”test” value=”1″ type=”checkbox”>
<label>測試文字x</label>
<br/><br/>
<input class=”inputcheckbox” name=”test2″ value=”2″ type=”radio”>
<label>測試文字x</label>
<br/><br/>
<input class=”inputcheckbox” name=”Text1″ type=”text” />
<label>文字</label>
<input  class=”inputcheckbox” name=”Text1″ type=”text” />
<label>文字</label>
<br/><br/>
<label>測試文字</label>
<input   class=”inputcheckbox” name=”Button1″ type=”button” value=”按鈕” />
<br/><br/>
<select class=”inputcheckbox” name=”Select1″>
<option>測試文字</option>
</select>
<label>測試文字</label>
</html>

而且我發現,不但解決了中文的問題,如果提示信息換成其他語言,基本上也能夠對齊,至少不會像開始那樣偏移太多。下面是截圖、代碼和一些例子:

07

<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN” “http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd”>
<html xmlns=”http://www.w3.org/1999/xhtml”>
<head>
<meta http-equiv=”Content-Type” content=”text/html; charset=UTF-8″ />
<title>測試vertical-align</title>
<style>
label{vertical-align:middle}
.inputcheckbox{vertical-align:middle;}
body{font-family:tahoma;font-size:12px;}
</style>
</head>
<body>
<input class=”inputcheckbox” name=”test” value=”1″ type=”checkbox”>
<label>測試文字x</label>
<br/>
<input class=”inputcheckbox” name=”test” value=”1″ type=”checkbox”>
<label>這是繁體中文</label>
<br/>
<input class=”inputcheckbox” name=”test” value=”1″ type=”checkbox”>
<label>次回から自動的にログイン</label>
<br/>
<input class=”inputcheckbox” name=”test” value=”1″ type=”checkbox”>
<label>English</label>
<br/>
<input class=”inputcheckbox” name=”test” value=”1″ type=”checkbox”>
<label>Чужой компьютер</label>
<br/>
<input class=”inputcheckbox” name=”test” value=”1″ type=”checkbox”>
<label>صفحات من ‏السعودية </label>
<br/>
<input class=”inputcheckbox” name=”test” value=”1″ type=”checkbox”>
<label>회원가입</label>
<br/>
<input class=”inputcheckbox” name=”test” value=”1″ type=”checkbox”>
<label>הפתוח</label>
<br/>
</html>

至此,我的研究過程告於段落。


發佈了16 篇原創文章 · 獲贊 6 · 訪問量 18萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章