[Layout] Web Design Part 7

以前在寫網頁的時候,曾經遇過這麼一件趣事。IE 光宗耀祖的 hasLayout 還不是那麼令人詬病的年代,為了解決 IE 與 Netscape 的動態效果不一致的狀況,不斷地查詢 position 定位問題時,曾經看過這麼樣一註解:

/* Don't ask, just do it. */

zoom: 1;

然後我就哭了。


定位、浮動與推齊

在盒子元件中,最讓人不高興的,大概就是定位點的問題。我們如果時常使用 position, float, clear 這三種屬性設定,那麼就會遇到區塊亂跑亂跳的情況。如果元件數量不多倒是還好,但是通常一個 Layout 元件數量都已經相當龐大,遇上這種問題有時候會讓人很無力。

position IN ACTION.

Position

float, clear IN ACTION.

Float and Clear

定位

首先你必須知道,定位屬性叫做 position,他有幾種可能的值:

  • inherit:繼承定位設定,依照父元件繼承而來的設定。
  • static:預設定位設定,依照文件元素擺放而使用預設設定,此時你若是額外設定 top, left, right, bottom 都是無效的。
  • relative:相對定位設定,依照父元件或鄰近元件的原點定位做相對位置設定。
  • absolute:絕對定位設定,依照父元件或是根元件的原點定位做絕對位置設定。
  • fixed:固定定位設定,依照根元件的原點定位做絕對位置設定。

這裡所描述的根元件,指的是 DOM Tree 的根(root),通常就是指最外層的 <body> 標籤。至於什麼叫做 DOM Tree,你先把他想成是一棵樹就好了。

定位功能在以往做動態網頁的時候相當常見,屏除我剛剛說的 IE 的 hasLayout 的問題之外(IE 表示:),基本上他是一個非常有利於排版的工具。但是,雖然定位點好用,且絕對精準,但是我也看過過度使用的切版設計。至於會造成什麼樣的悲劇,讓我們繼續看下去。

  • 只有盒子模型(Box module)才能定位
  • 絕對定位類型(fixed, absolute)不干擾相對定位類型(inherit, static, relative
  • 相對定位類型會互相干擾
  • 絕對定位其子元件倘若繼承或是也使用絕對定位,則一律以根元件原點定位為準
  • 相對定位棋子元件倘若使用絕對定位(僅限 absolute),則是以其父元件的原點定位為準
  • margin 留白特性會影響定位結果

當然,沒有什麼比實際範例更容易看出結果。

Position sample

<div id="container">
    <div id="box1" class="boxes"><h1>1</h1></div>
    <div id="box2" class="boxes"><h1>2</h1></div>
</div>
#container {
    position: inherit;
}
#box1 {
    position: absolute;
    top: 100px;
    left: 100px;
}
#box2 {
}

由此可以看出,由於 box1 使用了絕對定位(定位點是 x: 100px, y: 100px),所以他不會受到Breaking Rules的影響,而 box2 沒有任何定位設定,所以他依循盒子模型的特性,定位點回到左上角。你可以由 Tilt 所提供的畫面看出,box1box2 是同屬於同一個層,但是由於定位設計,他們兩個元素互相重疊了。

倘若我們多加了點文字呢?

Position sample

你會發現 box2 被往下推了,但是 box1 依然不受影響。這是由於 box2 會依循Breaking Rules的影響,所以他會將定位點往下一行。而這個往下的距離,則會受到許多設定上的干擾:

  • 父元件本身的行高設定
  • 相鄰元素本身的高度與行高設定
  • 相鄰元素本身的定位設定
  • 相鄰元素本身的浮動與推齊設定
  • 元素自身的 maring 設定
  • 元素自身的相對定位設定

Position sample

怎麼會有兩個行高 100px,但是結果卻不同?我剛剛有說過了,相對定位或是不使用定位,自身會受到相鄰或是父元件本身的設定,而有所影響。之所以會出現不同的情況,是因為在瀏覽器的預設值當中,<body> 這個標籤本身,就會對內容事先進行留白的動作。

所以,你所看到的,右下角的展示範例中,box1box2 本身是對齊的,這才是真正我們所要的結果。所以,當我們在使用定位點時,請不要忘記這幾項設定的干擾:

  • line-height
  • height
  • margin
  • padding
  • border
  • float

會不會太多因素啦?會,所以定位點的使用,並不建議用於內文與盒子模組相對複雜的環境當中。另外還有一種常用情況,就是相對定位中包含絕對定位。這樣說很籠統,我們直接看例子會比較能夠理解。

Position sample

請注意,定位方法 fixed 在這裡是無效的!雖然他也是屬於絕對定位的一種,但是他是相對於整個根元件來定位,也就是說,不管你是使用什麼方式將 fixed 包起來,他永遠都會根據 <body> 的原點做定位動作。

總括來說,定位功能對於排版上能夠提供較為直覺的方式。但是,相對複雜的影響因素卻很容易將結果給毀掉。對於定位屬性的使用上,我個人在使用上的建議:

  • 用於大型框架元素
  • 不要重複使用相對定位
  • 不要與浮動(float)設定混用
  • 事事沒有絕對(不要濫用 absolute

不要重複使用相對定位
其實根據標籤語言的結構來說,每一種元素對其相鄰元素都是相對的位子。所以,當你在相鄰或是子元素中大量使用相對定位,其實是沒有太大意義的。除非你有你的考量。
大量且重複的使用,不僅會直接破壞元素間的 Breaking Rules,也會讓整個 DOM Tree 結構變得難以維護,所以,在相對定位設定的同時,請先想想是否需要這麼做。

浮動與推齊

Float and Clear

圖片永遠是我們最佳良伴。所謂的浮動(float),顧名思義就是讓你的盒子元件起來。但是這個飄的動作,卻會打壞元素之間的Breaking Rules,所以,聰明的 CSS 又用了推齊(clear)來讓我們飄起來的元素,可以進行對齊的動作。

Float sample

請看 Tilt 的展示,他是起來的元素。

#box1 {
    float: left;
}
#box2 {
    float: right;
}

飆起來其實就只有三種設定:left, right, none,所以也沒什麼好解釋的。那麼推齊(clear)呢?他其實也只有三種:left, right, both,但是他需要解釋。

  • clear: left,將段落定位點設定在左邊,意思則是,清除目前的浮動元素段落的斷行規則,將斷行重新定位在左邊。
  • clear: right,將段落定位點設定在右邊,跟上述做一樣的動作,但是最後定位在右邊。
  • clear: both,清除目前所有段落定位點,取最長浮動段落文末為基準,清除所有斷行規則,重新定位在左邊。

我們重複剛剛的例子。

#box1 {
    float: left;
}
#box2 {
    clear: left;
    float: right;
}

Clear sample

這樣看得出 clear: left 做了什麼事情嗎?倘若,我們在兩個浮動元件中,加入一行字,會產生什麼結果?

<div id="container">
    <div id="box1" class="boxes"><h1>1</h1></div>
    <p>我是閃光洽!</p>
    <div id="box2" class="boxes"><h1>2</h1></div>
</div>

Clear sample

文字段落會因為浮動元件的佔位而往後移動。但是,文字段落的斷行規則不會因為浮動元件而有任何的改變。這一點,是跟定位元件有很大的不同。雖然,絕對定位在某方面,也能想像為一種浮動元件,但是,定位元件卻沒有推齊(clear),這種與斷行規則有關的設定可用,所以在應用上也是有相對落差的。

浮動元件,其實我們很常看到這種應用,只是或許你不清楚而已。

  • 導覽列的按鈕
  • 部落格的雙、多欄位設定
  • 齊頭式的表單元素
  • 輪播式元件、幻燈片效果等

浮動元件唯一要注意的地方,就是會干擾一般元素的擺放位置,因為他會產生佔位的關係。同時,浮動元件自身,對於留白的情況是不明確的(IE 表示:)。

這種情況就很常發生:

Clear sample

為什麼我的外框沒有跟著延伸?

Clear sample

我們只要多一個動作就能解決:

<div id="container">
    <div id="box1" class="boxes"><h1>1</h1></div>
    <p>我是閃光洽!</p>
    <div id="box2" class="boxes"><h1>2</h1></div>
    <div class="clear"></div>
</div>
#box1 {
    float: left;
}
#box2 {
    float: left;
}
div.clear {
    clear: both;
}

佔位
浮動元素特有的情況,雖然是浮動元件,但是還是與同層相鄰元件有段落的關係。特別的是,雖然他自身的寬度會佔據段落的寬度,但是,他的高度並不會直接影響段落的結果。同樣的,也不會對所屬父元件產生影響。
並且,在使用浮動元件時,其相鄰元件的段落是毫無關聯的。對其所屬父元件來說,可以使用推齊的動作,來達成高度佔位,也就是段落重設的效果。如上述例子一般。所以說,浮動佔位的推齊,是針對父元件,而自身,則與相鄰元素佔位有關,這點請牢記。

段落行高與 Breaking Rules

Line Height

行高其實很容易理解,就是一行字的高度。在 CSS 中,高度跟行高是不同的。當然,不同的高度也限制了行高的展示結果。如果高度小於行高,那麼你的文字區塊就會因為高度限制而被切掉

Breaking Rules則是比較特別的東西,通常,他由瀏覽器或是我們對於文字的一些特殊設定而決定。斷行、斷字的規則我們都可以通過樣式表來決定,不過,從哪個地方開始斷行,那些地方開始斷字,就只能依照輸出的容器來決定。

所以,文字的排版是相對困難的。

逢沢りな

逢澤莉娜

Rina Aizawa

只是說我也不知道我排起來怎麼可以這麼好看,一定是妹正的關係。

有關斷字、斷行,可以參考:CSS Text Level 3, 4. Line Breaking and Word Boundaries

Hina Chen
偏執與強迫症的患者,算不上是無可救藥,只是我已經遇上我的良醫了。
Taipei