以前在寫網頁的時候,曾經遇過這麼一件趣事。IE 光宗耀祖的 hasLayout
還不是那麼令人詬病的年代,為了解決 IE 與 Netscape 的動態效果不一致的狀況,不斷地查詢 position
定位問題時,曾經看過這麼樣一註解:
/* Don't ask, just do it. */
zoom: 1;
然後我就哭了。
定位、浮動與推齊
在盒子元件中,最讓人不高興的,大概就是定位點的問題。我們如果時常使用 position
, float
, clear
這三種屬性設定,那麼就會遇到區塊亂跑亂跳的情況。如果元件數量不多倒是還好,但是通常一個 Layout 元件數量都已經相當龐大,遇上這種問題有時候會讓人很無力。
position
IN ACTION.
float
, clear
IN ACTION.
定位
首先你必須知道,定位屬性叫做 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
留白特性會影響定位結果
當然,沒有什麼比實際範例更容易看出結果。
<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 所提供的畫面看出,box1
與 box2
是同屬於同一個層,但是由於定位設計,他們兩個元素互相重疊了。
倘若我們多加了點文字呢?
你會發現 box2
被往下推了,但是 box1
依然不受影響。這是由於 box2
會依循Breaking Rules的影響,所以他會將定位點往下一行。而這個往下的距離,則會受到許多設定上的干擾:
- 父元件本身的行高設定
- 相鄰元素本身的高度與行高設定
- 相鄰元素本身的定位設定
- 相鄰元素本身的浮動與推齊設定
- 元素自身的
maring
設定 - 元素自身的相對定位設定
怎麼會有兩個行高 100px,但是結果卻不同?我剛剛有說過了,相對定位或是不使用定位,自身會受到相鄰或是父元件本身的設定,而有所影響。之所以會出現不同的情況,是因為在瀏覽器的預設值當中,<body>
這個標籤本身,就會對內容事先進行留白的動作。
所以,你所看到的,右下角的展示範例中,box1
與 box2
本身是對齊的,這才是真正我們所要的結果。所以,當我們在使用定位點時,請不要忘記這幾項設定的干擾:
line-height
height
margin
padding
border
float
會不會太多因素啦?會,所以定位點的使用,並不建議用於內文與盒子模組相對複雜的環境當中。另外還有一種常用情況,就是相對定位中包含絕對定位。這樣說很籠統,我們直接看例子會比較能夠理解。
請注意,定位方法 fixed
在這裡是無效的!雖然他也是屬於絕對定位的一種,但是他是相對於整個根元件來定位,也就是說,不管你是使用什麼方式將 fixed
包起來,他永遠都會根據 <body>
的原點做定位動作。
總括來說,定位功能對於排版上能夠提供較為直覺的方式。但是,相對複雜的影響因素卻很容易將結果給毀掉。對於定位屬性的使用上,我個人在使用上的建議:
- 用於大型框架元素
- 不要重複使用相對定位
- 不要與浮動(
float
)設定混用 - 事事沒有絕對(不要濫用
absolute
)
不要重複使用相對定位
其實根據標籤語言的結構來說,每一種元素對其相鄰元素都是相對的位子。所以,當你在相鄰或是子元素中大量使用相對定位,其實是沒有太大意義的。除非你有你的考量。
大量且重複的使用,不僅會直接破壞元素間的 Breaking Rules,也會讓整個 DOM Tree 結構變得難以維護,所以,在相對定位設定的同時,請先想想是否需要這麼做。
浮動與推齊
圖片永遠是我們最佳良伴。所謂的浮動(float
),顧名思義就是讓你的盒子元件飄起來。但是這個飄的動作,卻會打壞元素之間的Breaking Rules,所以,聰明的 CSS 又用了推齊(clear
)來讓我們飄起來的元素,可以進行對齊的動作。
請看 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: 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
),這種與斷行規則有關的設定可用,所以在應用上也是有相對落差的。
浮動元件,其實我們很常看到這種應用,只是或許你不清楚而已。
- 導覽列的按鈕
- 部落格的雙、多欄位設定
- 齊頭式的表單元素
- 輪播式元件、幻燈片效果等
浮動元件唯一要注意的地方,就是會干擾一般元素的擺放位置,因為他會產生佔位的關係。同時,浮動元件自身,對於留白的情況是不明確的(IE 表示:)。
這種情況就很常發生:
為什麼我的外框沒有跟著延伸?
我們只要多一個動作就能解決:
<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
行高其實很容易理解,就是一行字的高度。在 CSS 中,高度跟行高是不同的。當然,不同的高度也限制了行高的展示結果。如果高度小於行高,那麼你的文字區塊就會因為高度限制而被切掉。
而Breaking Rules則是比較特別的東西,通常,他由瀏覽器或是我們對於文字的一些特殊設定而決定。斷行、斷字的規則我們都可以通過樣式表來決定,不過,從哪個地方開始斷行,那些地方開始斷字,就只能依照輸出的容器來決定。
所以,文字的排版是相對困難的。
逢沢りな
逢澤莉娜
Rina Aizawa
只是說我也不知道我排起來怎麼可以這麼好看,一定是妹正的關係。
有關斷字、斷行,可以參考:CSS Text Level 3, 4. Line Breaking and Word Boundaries