/ CSS

[Layout tech.] Web Design note with XHTML/CSS part 3

這次要講的重點是:

  • 再看視覺格式物件(Visual formatting model)中的 display 屬性
  • 列表與清單物件
  • 不用 TABLE 的表格
  • 很好很強大的特殊屬性:counter

首先,在閱讀這篇文章之前,請明確認知以下兩件事情:

  • IE6+7 sucks!
  • 本文作者是三尛咖!

有以上明確的認知之後,我們繼續(疑?)。

視覺格式物件當然不只限於 display 而已,但是定位(position)與浮動(float)在 上一篇 已經講得夠多了,所以我們這次就來提一下顯示(display)這個屬性。顯示(display)這個屬性的值在 CSS 2.1 的規範中相當多元:

  • block
  • inline-block
  • inline
  • list-item
  • none
  • run-in
  • table, inline-table, table-row-group, table-column, table-column-group, tabspan-header-group, table-footer-group, table-row, table-caption
  • inherit(這個屬性值就不多做介紹了,不要問我為什麼)

我所標明出藍色的部分,是最常見且常用的,而綠色的部分則是比較少人使用的部分,而紅色的部分,是我要特別說明一下的地方。我想可能很少人聽過或是用過 run-in 這個屬性值,它比較特別的地方在於,它被賦予屬性狀態是跟著整個 Box 元件的最後的狀態而定,假設 Box 元件最後被指定為區塊(block),則設定為 run-in 的元件也會跟著被指定為區塊(block),若是指定為行內(或譯內聯,inline)元件,則 run-in 元件就會被指定為行內(inline)元件。

會用上 run-in 的設定屬性的地方不多,目前能正常顯示 run-in 的瀏覽器也不多(Chrome、IE8、Opera,很抱歉 Firefox 3.0x 似乎不領情)。而大多會使用 run-in 屬性設定,都會配合 :after 與 :content 來使用,應用的對象多數是配合段落中的影像圖片,這個功能支援度並沒有很完整,起碼,我在 Chrome、IE8、Opera 中測試的結果,只有 IE8 與 Opera 顯示出相同的結果,Chrome 還是顯示出了錯誤的位置。

關於 run-in 我們還是到此為止,這個真的太冷門了。

接著我們來看 list-item 這個屬性值,顯而易見的,它其實就是清單(Lists)元件的一種,只是利用顯示(display)屬性將它表現出來。當然,既然是清單元件的一種,理所當然的,就可以使用清單元件的所有屬性設定。

	<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
	<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="zh-TW">
	<head profile="http://gmpg.org/xfn/11">
	<meta http-equiv="content-Type" content="text/html; charset=UTF-8" />
	<title>Simple Layout - display</title>
	<style type="text/css">
	<!--
	.before-runin, .after-runin {
	    border: 5px solid #efefef;
	    padding: 5px;
	    display: block;
	}
	.after-runin div.listitem {
	    display: list-item;
	    list-style-type: circle;
	    margin-left: 20px;
	}
	-->
	</style>
	</head>
	<body>
	<h1>Before:</h1>
	<div class="before-runin">
	    <div class="nonlist">A</div>
	    <div class="nonlist">B</div>
	    <div class="nonlist">C</div>
	    <div class="nonlist">D</div>
	</div>
	<h1>After:</h1>
	<div class="after-runin">
	    <div class="listitem">A</div>
	    <div class="listitem">B</div>
	    <div class="listitem">C</div>
	    <div class="listitem">D</div>
	</div>
	</body>
	</html>

清單結果展示

這樣應該可以很清楚明瞭的知道 list-item 這個屬性值在做甚麼事情了吧。

接著我們來看 table 系列的屬性值,當然,既然可以轉換成 table 系列的屬性值,那麼也可以使用 table 系列的屬性設定,這些設定全部是以 HTML 4 為基準,除了兩個屬性值無法顯示之外,其他屬性皆可以正常顯示,缺點是,這不像是真的 TABLE 一樣可以做到跨欄、跨行的設定,所以,這樣的顯示屬性只能很單純的畫出很工整的 Table 而已,並不像是 HTML 中的 TABLE 標籤那樣靈活。

	<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="zh-TW">
	<head profile="http://gmpg.org/xfn/11">
	<meta http-equiv="content-Type" content="text/html; charset=UTF-8" />
	<title>Simple Layout - display, table</title>
	<style type="text/css">
	<!--
	#table-item-inline {
	    display: inline-table;
	}
	#table-item {
	    display: table;
	}
	.tables {
	    width: 300px;
	    height: 100px;
	    border-top: 1px solid #000;
	    border-left: 1px solid #000;
	}
	.row-item {
	    display: table-row;
	    height: 40px;
	}
	.cell-item {
	    display: table-cell;
	    border-right: 1px solid #000;
	    border-bottom: 1px solid #000;
	    text-align: center;
	    vertical-align: middle;
	}
	.caption-item {
	    display: table-caption;
	    text-align: center;
	}
	-->
	</style>
	</head>
	<body>
	<div id="table-item" class="tables">
	    <div class="caption-item">Simple Layout</div>
	    <div class="row-item">
	        <div class="cell-item">Simple</div><div class="cell-item">Simple</div><div class="cell-item">Simple</div><div class="cell-item">Simple</div>
	    </div>
	</div>
	<div id="table-item-inline" class="tables">
	    <div class="caption-item">Simple Layout</div>
	    <div class="row-item">
	        <div class="cell-item">Simple</div><div class="cell-item">Simple</div><div class="cell-item">Simple</div><div class="cell-item">Simple</div>
	    </div>
	</div>
	<div id="table-item-inline" class="tables">
	    <div class="caption-item">Simple Layout</div>
	    <div class="row-item">
	        <div class="cell-item">Simple</div><div class="cell-item">Simple</div><div class="cell-item">Simple</div><div class="cell-item">Simple</div>
	    </div>
	</div>
	</body>

Display 結果展示

以上就是顯示(display)屬性在的完整應用設定。老實說,以現在多數的瀏覽器來說,這些設定在各家瀏覽器所顯示的結果可能會有所出入,就像是浮動與定位對於留白的顯示誤差是一樣的,所以,利用顯示來達到清單或是表格的效果,其撰寫與應用的方法有限,真正能夠比較完整的達到清單或是表格需求的,那就是浮動(float)設定。當然,要講浮動設定之前,希望你已經清楚的知道 Box 元件在顯示上的定位問題(還不知道的請參考 上一篇)。

在 HTML 中,我們很常使用清單標籤,諸如:<ol><li><ul><li><dl><dt><dd> 這三種標籤(什麼?沒聽過 <dl><dt><dd>?請參閱 HTML 4.01 10 Lists Definition lists )。這三種標籤除了可以利用 CSS 來美化顯示效果之外,另一個很大的用途就是,用來取代一些 TABLE 在做的事情,如同我在第一篇 所提到的按鈕就是一個例子。已經忘了?那就來個例子,順便,我們來看看 <dl> 標籤如何做出整齊的表單:

	<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="zh-TW">
	<head profile="http://gmpg.org/xfn/11">
	<meta http-equiv="content-Type" content="text/html; charset=UTF-8" />
	<title>Simple Layout - display, table</title>
	<style type="text/css">
	<!--
	h1 {
	    clear: both;
	}
	#ul-button {
	    border: 2px solid #1579bc;
	    background-color: #2385c3;
	    width: 700px;
	    height: 30px;
	    list-style: none;
	    margin: 0;
	    padding: 0;
	}
	#ul-button li {
	    color: #fff;
	    font-weight: bold;
	    width: 115px;
	    height: 24px;
	    float: left;
	    text-align: center;
	    padding-top: 6px;
	    cursor: pointer;
	}
	#ul-button li:hover {
	    background-color: #1579bc;
	}
	#ul-button li.firstItem {
	    border-right: 1px solid #005d96;
	}
	#ul-button li.lastItem {
	    border-left: 1px solid #74b4bc;
	}
	#ul-button li.item {
	    border-right: 1px solid #005d96;
	    border-left: 1px solid #74b4bc;
	}
	#ul-button li a {
	}
	#ul-button li a:hover {
	    text-decoration: none;
	}
	#dl-form dt {
	    float: left;
	    width: 80px;
	    height: 30px;
	}
	#dl-form dd {
	    float: none;
	    width: auto;
	    height: 30px;
	}
	-->
	</style>
	</head>
	<body>
	<h1>UL.button</h1>
	<ul id="ul-button">
	    <li class="firstItem">Home</li>
	    <li class="item">About us</li>
	    <li class="item">Contact us</li>
	    <li class="item">Sitemap</li>
	    <li class="item">News</li>
	    <li class="lastItem">Services</li>
	</ul>
	<h1>DL.form</h1>
	<dl id="dl-form">
	    <dt>Simple</dt>
	    <dd><input type="text" size="20" name="layout" /></dd>
	    <dt>&nbsp;</dt><dd>Please input something...</dd>
	    <dt>Simple</dt>
	    <dd><input type="text" size="20" name="layout" /></dd>
	    <dt>&nbsp;</dt><dd>Please input something...</dd>
	    <dt>Simple</dt>
	    <dd><input type="text" size="20" name="layout" /></dd>
	    <dt>&nbsp;</dt><dd>Please input something...</dd>
	<dl>
	</body>
	</html>

DL 表單結果展示

結束了嗎?當然,還沒有!清單元件除了能排出按鈕之外,當然也可以拿來畫表格。也許有人會質問,為什麼不拿剛剛的顯示屬性來畫就好?其實也可以(眾毆),不過當你遇到不同寬度、高度的欄位時,就不能使用顯示屬性來畫了,這個時候,清單元件就可以派上用場。但是!**請注意!利用清單元件來畫表格的缺點是,可能會有複雜的巢狀清單元件,在 HTML 中可能很容易理解(畢竟不會超過兩層),但是在 CSS 設定中,若是搞不清楚物件屬性的繼承順序的話,很容易將 CSS 寫爛掉。**所以,如果要利用清單元件來畫表格,請先衡量是否真有其必要性。

	<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="zh-TW">
	<head profile="http://gmpg.org/xfn/11">
	<meta http-equiv="content-Type" content="text/html; charset=UTF-8" />
	<title>Simple Layout - ul, table</title>
	<style type="text/css">
	<!--
	#ul-table {
	    list-style: none;
	    margin: 0;
	    padding: 0;
	    border: 0;
	    width: 328px;
	}
	#ul-table li.row {
	    clear: both;
	}
	#ul-table li.row div.cell {
	    float: left;
	    width: 80px;
	    height: 40px;
	    border: 1px solid #000;
	    text-align: center;
	}
	#ul-table li.row-cross-col {
	    clear: both;
	}
	#ul-table li.row-cross-col div.cell {
	    float: left;
	    width: 80px;
	    height: 50px;
	    border: 1px solid #000;
	    text-align: center;
	    overflow: none;
	    display: block;
	}
	#ul-table li.row-cross-col div:first-child {
	    width: 162px;
	    height: 102px;
	}
	-->
	</style>
	</head>
	<body>
	<h1>UL.table</h1>
	<ul id="ul-table">
	    <li class="row">
	        <div class="cell">1</div><div class="cell">2</div><div class="cell">3</div><div class="cell">4</div>
	    </li>
	    <li class="row-cross-col">
	        <div class="cell">1<br />2<br />3<br />4<br />5<br /></div><div class="cell">1<br />2</div><div class="cell">1<br />2</div>
	        <div class="cell">1<br />2</div><div class="cell">1<br />2</div>
	    </li>
	    <li class="row">
	        <div class="cell">1</div><div class="cell">2</div><div class="cell">3</div><div class="cell">4</div>
	    </li>
	</ul>
	</body>

UL Table 結果展示

最後,我來補充一點關於清單元件的東西。一般來說,我們要使用清單元件,無非就是兩種,一種是 <ol> 另一種是 <ul>,我想大家應該都知道差異性(計數與非計數)。現在,我們來試試看,不用 <ol> 標籤來做到 <ol> 標籤的效果。很神奇嗎?先來看看原始碼:

	<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="zh-TW">
	<head profile="http://gmpg.org/xfn/11">
	<meta http-equiv="content-Type" content="text/html; charset=UTF-8" />
	<title>Simple Layout - counter</title>
	<style type="text/css">
	<!--
	body {
	    counter-reset: chapter;
	}
	h1:before {
	    content: "Chapter " counter(chapter) ". ";
	    counter-increment: chapter;
	}
	h1 {
	    counter-reset: section;
	}
	h2:before {
	    content: counter(chapter) "." counter(section) " ";
	    counter-increment: section;
	    margin-left: 40px;
	}
	-->
	</style>
	</head>
	<body>
	<h1>H1.counter</h1>
	    <h2>H2.counter</h2>
	<h1>H1.counter</h1>
	    <h2>H2.counter</h2>
	<h1>H1.counter</h1>
	    <h2>H2.counter</h2>
	<h1>H1.counter</h1>
	    <h2>H2.counter</h2>
	</body>

Counter 結果展示

我在噗浪上,另外看到有人問說,<ol> 標籤的 start 這個屬性,在 HTML 中似乎要被取消了,其實,我想也是因為 CSS 的這個設定的關係,畢竟,很好用的呢!這種 counter 設定並不限制使用對象,換句話說,它可以使用在任何的標籤上,當然,如果你的數字不要從 1 開始(預設是 1),或是文章內數字要跳號,那麼你可以這樣設定:

	<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="zh-TW">
	<head profile="http://gmpg.org/xfn/11">
	<meta http-equiv="content-Type" content="text/html; charset=UTF-8" />
	<title>Simple Layout - counter</title>
	<style type="text/css">
	<!--
	body {
	    counter-reset: chapter +5;
	}
	h1:before {
	    content: "Chapter " counter(chapter) ". ";
	    counter-increment: chapter;
	}
	h1 {
	    counter-reset: section +2;
	}
	h2:before {
	    content: counter(chapter) "." counter(section) " ";
	    counter-increment: section section 2;
	    margin-left: 40px;
	}
	-->
	</style>
	</head>
	<body>
	<h1>H1.counter</h1>
	    <h2>H2.counter</h2>
	<h1>H1.counter</h1>
	    <h2>H2.counter</h2>
	    <h2>H2.counter</h2>
	<h1>H1.counter</h1>
	    <h2>H2.counter</h2>
	    <h2>H2.counter</h2>
	    <h2>H2.counter</h2>
	<h1>H1.counter</h1>
	    <h2>H2.counter</h2>
	    <h2>H2.counter</h2>
	    <h2>H2.counter</h2>
	    <h2>H2.counter</h2>
	</body>

Counter 結果展示

這樣,誰說清單非得要用 <ul><ol> 或是 <dl> 來排呢?您說是吧。