/ CSS

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

在這之前,請先拜讀:

開始之前,請先默念:

本文第一心法:IE6 sucks!

CSS 打從 1.0 到現在的 2.1,目前只有在 IE8 才是完全依照 CSS 2.1 的標準在走。這當然對於網頁設計的 ART 來說是很討人厭的事情。為什麼這麼說?這就像是在多年以前,要寫 DHTML 時,IE 與 Netscape 所使用的語法完全不同的狀況是一樣的,而 CSS 的應用就更糟糕,語法一模一樣,結果卻全然不同。這些差異其實很讓人傷腦筋,畢竟在全球的使用者中,IE 還是大宗,更恐怖的是 IE6 則是在這些 IE 使用者中的 90% 以上。

差在哪?就差在好的瀏覽器讓 ART 上天堂,IE6 只能讓 ART 住公司(沒有誤)。在 CSS 的標準規則裡面,最容易出現誤差的設定有下列幾項:

  • padding
  • margin
  • position
  • float
  • clear
  • line-height
  • height
  • width

眼尖的人應該會發現,我並沒有把選擇器(Selector)給列入,因為 IE6 sucks! 的關係,IE 對於選擇器能夠完全正常,也只有 IE8 而已,所以在這裡先不討論選擇器的問題。我們就針對上述的這些設定來研究瀏覽器之間的差異。

較常使用到上述設定的,大多為 Box model,這裡稍微說明一下(W3C 的圖不可愛):

Box model

以上就是 Box 元件的性質,包含了外邊留白(margin)、邊框(border)與內邊留白(padding),定位包含了上、右、下、左(top, right, bottom, left)與左上、右上、左下、右下(top left, top right, bottom left, bottom right)。內容(content)與邊框(border)都是屬於可見的屬性設定,留白(margin, padding)就屬透明屬性設定(意即不能使用顏色設定)。

眼花了嗎?沒關係,先來默念一下:

本文第二心法:200 + 800 > 1000

請不要懷疑,這個問題在接觸了 Box 元件之後一定會遇到,本心法可以回朔至第一心法,基本上是個無限迴圈。為什麼會發生這種狀況呢?其主要的原因在於各大瀏覽器對於定位、寬度以及留白都有不同的認知,而其最大的主因,請在默念一次本文第一心法:IE6 sucks!,沒有錯,你會在這篇文章中看見很多 IE6 sucks!。當然,這種問題並不單純只是出現在 IE 而已,如果對於 Box 元件屬性不熟悉,到哪種平台的瀏覽器你都會覺得奇怪。

請看圖說故事:

看圖說故事

當然,這個並不是什麼鐵則。這種情況在常用 TABLEs 的人應該常遇到。瀏覽器在讀取 HTML 的時候,大多會將這些 Box 元件的留白給個預設值(像是 body 就會給個 10px 之類的),好意是,不要讓你的 Box 元件全部都黏在一起,但是另一個影響就是,200 + 800 > 1000這種狀況就會浮現。而,為了避免這種情況,我們時常在許多 CSS 的設定檔案裡面看到這種設定:

	* {
	    margin: 0;
	    padding: 0;
	    border: 0;
	}

這是一個大家很容易遺忘的一個狀況:

真實顯示尺寸 = 設定尺寸 + 留白 + 邊框 (+ 行高)

所以,當我們使用 Box 元件進行排版時,就必須要注意 Box 元件本身的設定:

  • 寬度(width)
  • 高度(height)
  • 內外留白(margin, padding)
  • 邊框(border)
  • 行高(line-height)
  • 是否使用浮動(float)
  • 是否使用定位(position)

前四項,我想上面的圖片都已經解釋的很清楚,至於行高(line-height),請看圖:

行高

行高(line-height)其實是個很奇妙的設定,若是沒有強迫指定的話,他是會跟著 font 設定做 1:1 的比例顯示。麗如說,你的字型大小設定為 12pt,那麼你的行高就是 12pt 的系統指定行高,至於這個系統指定行高是多少,一般來說會多個 2px 上下,這個差距則是要看使用者端的顯示設定而有些微的差距。

上圖所描述的狀況就是,當行高(line-height)設定大於 Box 元件本身的高度(height)設定的時候,會將整個 Box 元件給撐開,造成了莫名的上邊內部留白狀況(padding-top)。這種因為行高產生的留白狀況,最常出現的是在使用 TABLEs 來切圖,而使用不同的 DTD 時,整個 TABLEs 中的 TR 與 TD 標籤就會裂開來,造成了原本使用 TABLEs 縫合的圖片,全部像是拼圖一樣被切開。

接著,我們來談談浮動(float)與定位(position),請默念法則:

本文第三心法:愛惜它(float)善用它(clear)忽略它(position

浮動與定位是在 CSS 中最常被拿來排版的兩個屬性。個人覺得,浮動要比定位來的更好用一點點。在這裡,希望你有一些基礎的 Layer(層)的概念,這樣浮動與定位對你來說應該就不難理解。再提到這個區塊之前,還需要任是一個屬性,叫做 z-index,你可以把它想做是三度空間裡面的 Z 軸,也就是除了寬度、高度之外的第三個"深度"。這個深度的應用在浮動或定位元件裡面非常常見,是用以指定 Box 元件在顯示的"前後順序"的依據。一般來說,這樣的前後順序都是依照 DOM Tree 的排列"由上而下"的順序做為預設的指定順序,而,z-index 則可以修改這樣的順序。

定位與深度

然而,在 DHTML 正夯的時候,定位(position)這個屬性幾乎無所不在,那我現在為什麼要說忽略它呢?其實原因不難,定位這樣的屬性較多應用於複雜,且不易切割的版型上,加上現在瀏覽器顯示不一的狀況,定位這個屬性的使用時機與使用方向就變的比較模糊。且,定位屬性設定中,除了常見的 absoluterelative 較為常用外,像是 static(預設值),fixedinherit 就較少人使用。而,absoluterelative 這兩個屬性值,會依照 Box 元件的從屬關係而有不同的反應(結果)。

簡單的說,Box 元件在使用 position 時,會因為元件本身的 DOM 結構與 z-index 的設定而有所不同,這不僅僅只會發生在 DOM 或是 CSS 設定上,也會因為瀏覽器的不同而有產生不一樣的結果。

DOM 定位

反觀浮動(float)屬性,就單純的多,它只有四種屬性值:left, right, none(預設值)與 inherit。為什麼說它單純,從屬性值來看,我們可以很簡單的理解,它只能左右浮動,或是依據使用者給予該屬性的預設值(inherit),或是根本不浮動(none)。這樣的設定我們可以很單純的將某些需要排版的物件,利用浮動與留白(padding, margin),甚至是尺寸(width, height),來決定我們的浮動物件在畫面上的位置。

這樣跟定位有什麼不同?不同的地方大致上有:

  • 浮動與解析度無關,定位物件是以瀏覽器 document 的尺寸為基準。
  • 浮動物件只影響同樣為浮動的物件,類似定位物件中的 relative 設置,但 relative 設置會因為其他 Box 物件的位置而有所不同。
  • 推齊(clear)屬性設定對定位(position)屬性設定無效果,僅對浮動(float)有效。
  • 定位物件無論 DOM 結構如何,皆會互相影響,包含父元件內的子成員也會對父元件層級的成員造成影響,浮動物件則依照 DOM 結構而定,不會越級干擾。
  • **兩者混用會造成 DOM 混亂。

我們來看看真實範例(本範例不包含定位與浮動混用狀況):

<div id="container">
    <h1>Container</h1>
</div>
 
<div id="item1">
    <h1>Item 1</h1>
</div>
 
<div id="item2">
    <h1>Item 2</h1>
</div>
 
<!-- "clear" cannot apply in "position" CSS setting. -->
<br class="clear" />
 
<div id="item3">
    <h1>Item 3</h1>
</div>
 
<div id="item4">
    <h1>Item 4</h1>
</div>
 
<div id="item5">
    <h1>Item 5</h1>
</div>
 
<!-- "clear" can apply in "float" CSS setting. -->
<br class="clear" />
 
<div id="item6">
    <h1>Item 6</h1>
    <div id="item7">
        <h1>Item 7</h1>
    </div>
</div>
 
<!-- "clear" can apply in "float" CSS setting. -->
<br class="clear" />
 
<div id="item8">
    <h1>Item 8</h1>
    <div id="item9">
        <h1>Item 9</h1>
    </div>
</div>
 
<div id="item10">
    <h1>Item 10</h1>
</div>
#container {
    width: 280px;
    height: 280px;
    padding: 10px 10px;
    margin: 0;
    border: 1px solid #ff3333;
    background-color: #efefef;
}
 
#item1 {
    position: relative;
    top: -200px;
    left: 200px;
    width: 280px;
    height: 280px;
    padding: 10px 10px;
    margin: 0;
    border: 1px solid #ff3333;
    background-color: #efefef;
    filter: alpha(opacity=50);
    -moz-opacity: 0.5;
}
 
#item2 {
    position: relative;
    top: -400px;
    left: 400px;
    width: 280px;
    height: 280px;
    padding: 10px 10px;
    margin: 0;
    border: 1px solid #ff3333;
    background-color: #efefef;
    filter: alpha(opacity=50);
    -moz-opacity: 0.5;
}
 
#item3 {
    position: relative;
    top: 0px;
    left: 0px;
    width: 280px;
    height: 280px;
    padding: 10px 10px;
    margin: 0;
    border: 1px solid #ff3333;
    background-color: #efefef;
}
 
#item4 {
    float: right;
    width: 280px;
    height: 280px;
    padding: 10px 10px;
    margin: 0;
    border: 1px solid #ff3333;
    background-color: #efefef;
}
 
#item5 {
    float: right;
    width: 280px;
    height: 280px;
    padding: 10px 10px;
    margin: -800px 200px 0px 0px;
    border: 1px solid #ff3333;
    background-color: #efefef;
}
 
#item6, #item8 {
    width: 480px;
    height: 480px;
    padding: 10px 10px;
    border: 1px solid #ff3333;
    background-color: #efefef;
}
 
#item7 {
    float: right;
    width: 280px;
    height: 280px;
    padding: 10px 10px;
    border: 1px solid #ff3333;
    background-color: #efefef;
}
 
#item9, #item10 {
    position: relative;
    top: 100px;
    left: 100px;
    width: 280px;
    height: 280px;
    padding: 10px 10px;
    border: 1px solid #ff3333;
    background-color: #efefef;
}

範例結果展示

由以上的範例,應該可以很清楚的分辨定位與浮動的不同。特別是在 Item 8, Item 9 與 Item 10 的關係,我已經把 Item 9 與 Item 10 的原始位置用圖示標記出來,**倘若拿掉那個粉紅色方塊,你能夠知道為什麼 Item 10 跟 Item 8 會有那一段莫名的空白嗎?**這就是子元件影響到父元件層級的一個例子,由於定位物件是針對整個 document.body 做為參考,所以對於 DOM 的結構規範是沒有作用的。另外,定位物件會因為解析度的關係而有不同的結果,所以你若是利用上述的範例所產生的畫面,可能跟我所看見的不同。

總結來說,定位元件並不是很適合拿來做版面的排版,當然這是個人的感想,在許多 CSS 免費樣版提供的平台中,還是有不少的 CSS 是使用定位的方式來設定版面。除非是做到良好的控制,否則對於會變動的內文樣式來說,浮動元件也許是比較適合拿來做排版。畢竟,配合浮動元件的另一個利器:推齊(clear)也是很好很強大的。

推齊

不知道這樣,你能了解到推齊(clear)的美好嗎?

最後,請默念一千遍:IE6 sucks!