一、position

相對定位與絕對定位的應用

Manifold

上面圖形的原始碼是:

    <div style="border: 1px solid; width: 200px; height: 120px;">
        <div style="color: blue;">Manifold</div>
    </div>

問題來了,我想把 Manifold 移到最右邊,要怎麼做?

調整 CSS 提供的 position 屬性,可以達到我們的要求。 先把黑色框框 (Box1) 的 position 屬性設成 relative, 這會使得 Box1 裡面元素的位置都是相對於 Box1。 再把 Manifold 的 position 屬性設成 absolute, 這使得我們可以藉由調整 Manifold 的 top, left, right, bottom 屬性來控制 Manifold 的位置。 至於要靠右的話,把 right 設成 0。 修改之後的原始碼如下:

    <div style="position: relative; border: 1px solid; width: 200px; height: 120px;">
        <div style="position: absolute; color: blue; right: 0;"> Manifold</div>
    </div>

圖形如下:

Manifold

如果想把 Manifold 移到右下角要怎麼做呢?聰明如你,應該知道答案了吧,沒錯,就是:

    <div style="position: relative; border: 1px solid; width: 200px; height: 120px;">
        <div style="position: absolute; color: blue; bottom: 0; right: 0;"> Manifold</div>
    </div>

圖形如下:

Manifold

通常會留一點空間,而不是把 Manifold 放在完全靠右下角的位置,圖形如下:

Manifold

原始碼是:

    <div style="position: relative; border: 1px solid; width: 200px; height: 120px;">
        <div style="position: absolute; color: blue; bottom: 3px; right: 6px;">Manifold</div>
    </div>
CSS 排版觀念 position 參數說明
position 參數
/ 參數說明
absoluterelativestatic(預設值)fixed
中文意義絕對位置相對位置靜態位置固定位置
畫面位置參考基準父元素內容區邊界原本應該在的位置不變不指定:原本應該在的位置
指定:螢幕視窗最大可視範圍邊界 (或框架邊界)
移動參考基準文件文件文件螢幕視窗最大可視範圍
可改變顯示位置
可調整大小display 為 block :是
display 為 inline :否
display 為 block :是
display 為 inline :否
從顯示流程中去除

當我們對元素的 position 屬性,指定了 absolute、 relative 或 fixed 後,這個元素就可以移動了。我們可以用 top, left, right, bottom 這四種屬性來指定元素要呈現的位置。

由於 IE 不支援 position: fixed ,使得固定位置這個好用的技巧一直不受大家的重視。但在這裡我還是提一下。你可以使用 FireFox 來感受一下固定位置的強大威力,或是等待新版的 IE 支援。

接下來我們來解釋上面的表列裡,每個參數說明的意義。

畫面位置參考基準

以絕對位置 (position: absolute) 而言,故名思義,它是以父元素的邊界為絕對起點。例如如果我們設定 top: 50px ,那麼這個元素就會在距離父元素內容區上邊界 50px 的地方呈現,如下圖:

position: absolute

補充:如果父元素的 position 不是 absolute 或 relative 時,那麼元素的位置就會再對應到父元素的上層元素;如果其親代元素的 position 都沒有設定 absolute 或 relative 時,就以螢幕視窗最大可視範圍邊界為基準。

而以相關位置 (position: relative) 而言,其意義就是相對於原本的位置。例如我們指定 top: 50px 時,那麼這個元素就會從原本應該呈現的位置往下移動 50px 。如下圖,紅色虛線部份就是未設定 position: relative 前,元素原該應該在的位置:

position: relative

而固定位置 (position: fixed) 指的就是固定在螢幕視窗最大可視範圍上,如果不指定位置 (top, left, right, bottom) 時,那元素就會固定在原本的位置;而指定位置後,就會以螢幕視窗最大可視範圍的邊界為絕對基準點。如果頁面內容超過螢幕視窗最大可視範圍大小時,那麼不論我們如何捲動頁面,元素都會固定在螢幕視窗最大可視範圍上我們所指定的位置。

移動參考基準

當頁面可以捲動的時候,absolute 、 relative 、 static 都會跟著移動。只有 fixed 會固定在螢幕視窗最大可視範圍上,不會跟著移動。

可改變顯示位置

就是我們可以透過指定元素的 top, left, right, bottom 四個屬性,使元素改變顯示位置。如果元素是 position: static 時,會自動忽略所設定的 top, left, right, bottom 。

可調整大小

我們可以透過 width, height 來調整元素內容區的大小,不過當 position 是 relative 或是 static 時,元素的 display 屬性必須為 block 才可調整其大小。

從顯示流程中去除

顯示流程的意義就是頁面上的每一個元素的呈現,換句話說,就是該元素會出現的位置,及其佔用的空間等等。

我們可以將原來的頁面想成是一個圖層,每個元素都是一個一個緊接在前一個元素後面。如下圖,在尚未指定 position 時,粉紫色區塊會緊接在淺藍色區塊後。

從顯示流程中去除_1

請注意,我在這裡提到的圖層,指的是瀏覽器去解譯 HTML 後,將元素呈現出來的圖層,而非一般我們所認為,以絕對位置呈現的圖層;你可以把它想像成是 Photoshop 裡的圖層。

當我們指定淺藍色區塊的 position 屬性為 absolute 或 fixed 後,淺藍色區塊就會跑到另一個圖層;而粉紫色區塊因為淺藍色區塊已經從原圖層的顯示流程中去除了,所以它就自動往上跑。如下圖,紅色虛線就是粉紫色區塊原本的位置。

從顯示流程中去除_2

而元素如果指定為 relative 時,雖然也能移動,但原本的頁面圖層還是會保留該元素所佔有的空間。

後記

或許你在看完這篇文章之後,還是無法很清楚地了解 position 屬性的運作方式。建議你打開你的瀏覽器 (最好是用 FireFox),再用你慣用的 HTML 編輯器去試試它們之間的差異。然後回來看看這篇文章,你也許就能明白我的意思。

補充:如果頁面在框架裡時 (frame 或 iframe) ,所有參照螢幕視窗最大可視範圍邊界的元素就會改為參照框架邊界。

二、float

問題

假設你要將一堆縮圖連結到較大尺寸的版本 – 這種網頁相當常見。除此之外,你希望每張縮圖的正下方都有個簡短的標題。接著,為了有效利用瀏覽器視窗的空間,你希望讓縮圖跟標題成對地排成一列,並會隨瀏覽器視窗寬度自動分行 (wrap,即流動式設計)。隨著最後一個要求,我們放棄表格,進入了 CSS 的王國。

一步步來

讓我們一步步來。第一個要求是縮圖的正下方要有個標題。作法相當直接了當:在你的HTML 裡放上圖片,接著一個斷行 (BR),再把標題放在一個段落 (P) 裡並且置中 (利用CSS)。

接著我們要讓這些縮圖跟標題成對地排列在瀏覽器視窗裡。使用表格排版時,這一對對的縮圖跟標題會被分別放置在 TD 裡。在使用 CSS 排版時,我們要把它們分別放置在 DIV 裡。為了讓它們能水平排列在視窗上,我們用 CSS 讓這些 DIV 往左浮動 (FLOAT)。

這時候 CSS 看起來應該像這樣:

div.float {float: left;}
div.float p {text-align: center;}

而 HTML:

<div class="float">
  <img src="image1.gif" width="100" height="100" alt="圖 1" /><br />
  <p>標題 1</p>
</div>

<div class="float">
  <img src="image2.gif" width="100" height="100" alt="圖 2" /><br />
  <p>標題 2</p>
</div>

<div class="float">
  <img src="image3.gif" width="100" height="100" alt="圖 3" /><br />
  <p>標題 3</p>
</div>

而在瀏覽器裡應該會看到:

圖 1

標題 1

圖 2

標題 2

圖 3

標題 3

 

下一個要求得靠 CSS 解決。我們要讓圖片跟標題成對地自動換行,以配合瀏覽視窗的寬度。讓 DIV 往左浮動 (FLOAT) 已經解決了這個問題。只要我們多放幾張縮圖,它們就會在瀏覽視窗裡自動換行 (只要改變瀏覽視窗的寬度,你就可以看到流動式設計的作用):

圖 1

標題 1

圖 2

標題 2

圖 3

標題 3

圖 1

標題 1

圖 2

標題 2

圖 3

標題 3


現在假設你希望同時在網頁上顯示好幾類的縮圖,並利用背景顏色或邊界等外觀條件幫它們分組。這時候只要用一個容器 (container) DIV 把它們包在一起就好:

div.container {border: 2px dashed #333;background-color: #ffe;}

但這時候麻煩來了。當你在 CSS 裡將一個元件浮動 (FLOAT) 以後,它就不再佔據任何 "空間",因此背景及邊界都會在圖片的正下方出現,而不是繞著圖片。所以我們必須在容器 DIV 裡多放點東西,比方說一個間隔 (spacer) DIV:

div.spacer {clear: both;}

其次是 HTML (注意在容器 DIV 的上下方都有個間隔 DIV):

<div class="container">
<div class="spacer">
  &nbsp;
</div>

<div class="float">
  <img src="image1.gif" width="100" height="100" alt="圖 1" /><br />
  <p>標題 1</p>
</div>

<div class="float">
  <img src="image2.gif" width="100" height="100" alt="圖 2" /><br />
  <p>標題 2</p>
</div>

<div class="float">
  <img src="image3.gif" width="100" height="100" alt="圖 3" /><br />
  <p>標題 3</p>
</div>

<div class="spacer">
  &nbsp;
</div>

</div>

結果如下:

 
圖 1

標題 1

圖 2

標題 2

圖 3

標題 3

 

根據 sam marshall 的原始碼製作。

巢狀 DIV 與巢狀 TABLE 有什麼不一樣?

好吧,我們有了一堆的巢狀 (nested) DIV,這比巢狀表格好在哪裡?答案是在於這些標籤的設計觀點上。DIV 暗示著一種邏輯或結構上的分組,即使它們以巢狀表示,仍然具有標記的結構性。在我們的例子裡,我們把縮圖跟它們的標題分成一組 (第一層),再將這些成對的縮圖跟標題依照相似性分組 (第二層)。這些都是利用 DIV 標籤把結構上的分組處理得相當好的範例。

然而表格暗示的是一種行與列的標頭 (header) 跟每個欄位資料的關係。當我們利用表格設計版面時,我們就喪失了表格結構的意義。讓我們回過頭來用 HTML 設計版面,巢狀表格只會讓問題複雜化。

表單功能

另一個常見的表格排版應用是排列表單 (FORM) 裡的元件與描述。關於這是不是表格的合適應用尚有很多爭論,而就像我們即將看到的,CSS 技術對類似的排版需求也很有用。

一個典型的表單版面裡,在左方的是描述,緊靠著右邊界,在右方的是元件,緊靠著左邊界。一切事物都在中央交會:

姓名:
年齡:
鞋子尺寸:
附註:
 

根據 Eric Meyer 的原始碼設計概念製作。

上面這個表單沒有使用到表格。我們又再度使用到浮動 (FLOAT) 來達成定位的工作。戲法是這樣的:我們用一個 DIV 模仿表格的列。然後我們創造兩個 SPAN,一個給描述、另一個給元件。把描述的 SPAN 往左浮動,元件的 SPAN 往右浮動。讓描述 SPAN 裡的文字往右靠,讓元件 SPAN 裡的文字往左靠。

所以 CSS 應該長這樣:

div.row {clear:both;padding-top:10px;}
div.row span.label {float:left;width:100px;text-align:right;}
div.row span.formw {float:right;width:235px;text-align:left;}

上面的 CSS 也設了 SPAN 的寬度。寬度可以像是範例裡的絕對值,或者也可以用百分比表示。百分比最多是到 100% 或少一點點,依照你設的留白跟邊界而定 (還有你設計的容器)。在範例裡我用另一個 DIV 把表單包起來,以設定邊界與背景。

範例 HTML:

<div style="width: 350px; background-color: #cc9; border: 1px dotted #333; padding: 5px; margin: 0px auto";>
  <form>
    <div class="row">
      <span class="label">姓名:</span>
      <span class="formw"><input type="text" size="25" /></span>
    </div>

    <div class="row">
      <span class="label">年齡:</span>
      <span class="formw"><input type="text" size="25" /></span>
    </div>

    <div class="row">
      <span class="label">鞋子尺寸:</span>
      <span class="formw"><input type="text" size="25" /></span>
    </div>

    <div class="row">
      <span class="label">附註:</span>
      <span class="formw">
        <textarea cols="25" rows="8">
        快! 來寫點東西......
        </textarea>
      </span>
    </div>

  <div class="spacer">
  &nbsp;
  </div>

 </form>

</div>

追求卓越

你也許會注意到,上面容器 DIV 的 STYLE 裡有一個屬性:margin: 0px auto;。在符合標準的瀏覽器裡,它會讓 DIV 往中間對齊。一些瀏覽器 (如 Windows 底下的 IE5.x) 會忽略這一點,卻會錯誤地讓有 text-align: center 的 DIV 往中間對齊。想讓 DIV 在這些瀏覽器往中間對齊的話,你可以用有 text-align: center 的 DIV 把另一個有 margin: 0px auto; 的 DIV 包起來 (裡面的 TEXT-ALIGN 是 left,所以文字會正常排列)。詳見 Rob Chandanais 在 Layout Reservoir 網站撰寫的置中對齊技術(1, 2)。

分隔差異

在處理本質上相對的事物時,也常會用到與前面類似的表格排版設計。這次你不是讓它們在中央交會,而是讓兩個元件擺在瀏覽器視窗的兩側。這也許是一個你想讓商標放在頁面右上角,而讓導覽元件放在頁面左上角的案例:

首頁 > 產品[商標]

在這裡我們使用跟表單範例裡一樣的 DIV.ROW,但這次會使用不同的 SPAN。左邊的 SPAN 往左浮動,而且文字往左靠。右邊的 SPAN 往右浮動,而且文字往右靠。

CSS:

div.row span.left {
  float: left;
  text-align: left;
  font-weight: bold;
  color: #fff;
  width: 49%;
  }
div.row span.right {
  float: right;
  text-align: right;
  font-weight: bold;
  color: #fff;
  width: 49%;
  }

HTML:

<div style= "width: 90%; background-color: #666; border: 1px solid #333; padding: 0px; margin: 0px auto;">
    <div class="spacer"></div>
    <div class="row"><span class="left">首頁 > 產品</span><span class="right">[商標]</span></div>
    <div class="spacer"></div>
</div>