關於表格的直覺印象,就是由多個單元格(cell)整齊排列而成的元素,可以明確看出行(row)和列(column)。這可以聯想到Excel,由Excel在資料處理和統計上的地位,就可以理解網頁中表格的意義。
使用表格很簡單,但有時候表格最終為每一個格子呈現的狀態,可能不是你想要的。比如說某些格子出現了換行,然後整個表格就因為換行看起來十分不美觀。尤其是用於資料呈現的表格,寬度分配是一個很重要的主題,你可能需要為每一列格子可能呈現的資料狀況,並對表格的總寬度做精打細算。
同時,表格都會設定border-collapse:collapse;和border-spacing:0;。這也是應用程式表格最常用的做法,Normalize.css把這部分當作了初始化定義。
兩個演算法
元素上的css屬性table-layout,將決定表格在佈局計算時所應用的演算法。它有兩種值,auto和fixed。在通常情況下,都使用預設值auto。 這兩種演算法的差異在於表格的寬度佈局是否與表格中的資料內容有關。本文會分別討論這兩種取值時,表格的佈局計算原理。
自動表格佈局-auto
自動表格佈局的特點是,表格的寬度佈局與表格中的所有資料內容有關,它需要在取得所有表格內容後才能確定最終的寬度佈局,然後再一起顯示出來。
如此看來,重點就是「內容相關」了。如果表格定義了固定寬度(這裡是500px),而所有的儲存格都不定義寬度(只討論css定義寬度),會如何呢?來看結果:
上面這個表格中,空白的部分是寫了 空格。經過比較,可以發現以下幾點:
第2列和第3列寬度相同。
第1列的寬度和後面任一列的寬度比似乎是2:1。
加上邊框和內邊距,所有欄位的寬度總合,等於表格定義的寬度。
每個單元格都沒有定義寬度,所以寬度佈局完全由具體的內容資料(文字資訊)決定的。如何解釋這樣的結果呢?可以先直觀地推測這樣的邏輯:
第1步,從每一列中選取文字內容最多(理解為不換行的情況下,文本所佔據的寬度最寬)的,作為“代表” 。
第2步,比較各列的「代表」的寬度,然後依照它們的寬度比例關係,為它們分配表格的總寬度,包括邊框和內邊距。
參考上面的邏輯,再來反觀一下前面的表格,是不是挺有些道理?注意,前面說寬度比「似乎」是2:1,這個會是?來看看去掉內邊距的版本:
用前端調試工具具體看一下上面的單元格的寬度,你會發現這個表格和之前不同,比例已經非常接近2 :1(是的,還有的這一小點是因為邊框,但是沒有邊框就沒辦法區分列了)。
可見,在分析寬度比例關係的時候,是會把內容寬度和內邊距,以及邊框都考慮在內的。這也說明,不是衡量文字的數目,而是衡量文字在不換行狀態所能佔據的寬度(這裡的2:1來自中文漢字是等寬的)。使用內邊距自然只是為了做出更美觀的表格 :) 。
有寬度定義的時候,又會怎麼樣呢?下面是一個部分單元格有寬度定義的表格:
它的對應html程式碼是:
<table class="exhibit_table">
<tr>
<th>一二</th>
<th style="width:200px;"> </th>
<th> </th>
</tr>
<tr>
<td style="width:5px;"> </td>
<td></td>
<td> </td>
</tr>
<tr>
<td> </td>
<td style="width:70px;"> </td>
<td>一二三四</td>
</tr>
</table>
登入後複製
##上面這個表格可以發現以下幾點: 寬度定為5px的單元格,實際呈現寬度是13px,這正好是單一漢字的寬度,同一列的有漢字的單元格則以最小單元格寬度的形式排列文字(所以,換行了)。 寬度設定為200px的儲存格,實際呈現寬度是200px,儘管同列還有一個寬度70px的定義。
沒有確切寬度定義的第3列,最後得到了表格在分配完第1列和第2列後全部的剩餘寬度。
對此的推論是,存在寬度定義和不存在寬度定義的列都有的情況時: 如果單元格定義寬度小於其內容的最小排列寬度(和不換行排列方式相反,盡可能多行排列在單元格內時,單元格所需的寬度),則該單元格所在的列,都會以最小排列方式呈現內容。 如果在同一列中,則儲存格的內容寬度(不換行形式,後文這個字都是這個意思)小於該列中最大的寬度定義,則該列的實際寬度等於該寬度定義。
不存在寬度定義的列,會先由表格分配寬度給有寬度定義的列之後,再分配給它們(同樣,它們之間的比例取決於內容寬度)。
最前邊的沒有寬度定義的可以看做情況1,這裡有的列有寬度定義,有的又沒有,可以看做情況2。下面是情況3,也就是所有的列都有寬度定義時:
對應html程式碼:<table class="exhibit_table exhibit_table_with_no_padding">
<tr>
<th style="width:50px;"> </th>
<th style="width:50px;"> </th>
<th style="width:100px;"> </th>
</tr>
<tr>
<td> </td>
<td> </td>
<td> </td>
</tr>
<tr>
<td> </td>
<td> </td>
<td> </td>
</tr>
</table>
登入後複製
上面的表格中,去掉了內邊距,因此可以清楚地由寬度定義值,得到這3列的寬度比例是2:1:1。這裡還有一個條件,就是儲存格內的內容寬度不超過寬度定義值。經過測試,IE7及以下在內容超過寬度定義值和其他瀏覽器表現不同。 從這個表格範例可以知道,如果所有的列都有寬度定義,而這些寬度定義的值的和小於表格的寬度,則表格會在分配完它們寬度定義值所對應的寬度後,繼續把剩餘寬度,按照它們的寬度比例,也分配給它們。 以上即是自動表格佈局,且表格本身是定義了固定寬度時,3種情況的分析。如果表格本身不定義寬度,還會有更多情況,而且會和表格的包含塊(containing block,詳情)有關,如果以後有合適機會,再做討論(所謂文章篇幅有限...)。
固定表格佈局-fixed
固定表格佈局的特點是,表格的寬度佈局和表格中的資料內容無關,只需要接收到表格第一行的信息,就可以確定最終的寬度佈局,並開始顯示。 固定表格佈局是「內容無關」的,而且它強調「第一行」。請看下面這個表格範例:
對應html程式碼:<table class="exhibit_table exhibit_table_fixed">
<tr>
<th style="width:50px;"></th>
<th>一二</th>
<th>一二三四</th>
</tr>
<tr>
<td>艾丝蒂尔·布莱特</td>
<td width="1000px;"> </td>
<td> </td>
</tr>
<tr>
<td style="width:5px;"> </td>
<td> </td>
<td> </td>
</tr>
</table>
登入後複製
固定表格版面的邏輯簡單很多,表述如下: 只取第一行的信息,忽略第一行之後的所有單元格的內容,及寬度定義 在第一行中,如果單元格有寬度定義,則先分配它們所需的寬度,然後剩餘的寬度平均分配給沒有寬度定義的單元格
第一行的單元格的寬度分配將決定表格的寬度佈局,第一行之後的內容不會再改變佈局。
還要注意的時候,使用固定表格佈局,則一定要給表格元素定義寬度,如果它的寬度沒有定義(也就是auto預設值),瀏覽器會改用自動表格佈局。
結尾宣告#
與表格有關的其實還有
、
、
、等元素,只是在最常見的用法中,並不需要用到它們。實際上,它們也在表格的佈局計算的考慮之內。再加上還有一個儲存格合併的情況,你大概可以想像到表格佈局計算其實是多麼複雜的東西。 W3C的文件提到,表格的佈局計算(自動表格佈局)尚沒有成為規範。關於W3C對錶面佈局計算的說明,請參考Table width algorithms。
結語
其實就表格佈局計算原理這一點,做這樣細緻的推斷,並沒有太多實用性。只是說,在需要解決細節問題的時候,有這些資訊做參考的話,會有所幫助,儘管這樣的機會不多。
不過,可以就本文的內容,得到一個比較有意義的結論:表格定義寬度,所有單元格都不定義寬度,那麼自動佈局的表格會盡可能讓你的所有數據都不換行,如果碰到換行影響美觀的情況,說明必須精簡資料或減少邊距,而不是再自行嘗試重做寬度分配。
這次做這種實測和推斷,感到針對具體情況細分後再說明,會比一次性系統地完整表述,更容易理解,也許算是語文練習?
更多HTML表格佈局實際使用相關文章請關注PHP中文網!