原文 http://learn.shayhowe.com/advanced-html-css/detailed-css-positioning
當構建頁面排版時,有不同的方法可以使用。使用哪一種方法取決於具體頁面的排版要求,在不同的情況下,某些方法可能好過於其他的方法。
比如,可以使用若干個浮動元素來構建一個整潔簡潔的頁面排版。或者,如果需要更復雜的排版要求,可以考略使用其他方法,比如使用相對定位和絕對定位。
在這篇文章中,我們首先要討論元素浮動;然后,我們要討論如何使用x,y和z軸控制元素的位置。
元素浮動
當構建一個頁面的排版時,使用元素浮動是一種直觀的方法去控制元素的位置。元素浮動可以讓一個元素靠近或者遠離另一個元素。它根據一個元素的大小和其父節點容器的大小來構造這個元素在排版中與其他元素之間的關系。
當一個元素被浮動時,這個元素是挨着前一個元素,還是出現在新的一行?這取決於它相鄰元素的位置。
當然,元素浮動在提供強大威力的同時,也帶來了很多問題。一個著名的問題就是,當一個父節點包括了若干浮動的子元素時,父節點的排版會考慮到浮動子元素的大小和位置,但是子元素並不會影響父節點的大小。在這種情況下,父節點的height變成了0,並且忽略其他屬性。 很多時候,這個問題沒有被注意到,特別是當父節點沒有附合任何的CSS樣式,而且嵌套的元素也看上去被正確地排列了。
如果沒有正確地排列嵌套元素,那么可能引發排版上的錯誤。請參閱下面的這個例子, 類名為.box-set的DIV容器應該有淺灰色的背景,但是因為其嵌套元素都是浮動元素,所以原本期望的背景色沒有出現。如果你查看.box-set的盒模型,你會發現它的height值為0。
<div class="box-set"> <div class="box">Box 1</div> <div class="box">Box 2</div> <div class="box">Box 3</div> </div>
.box-set { background: #e8eae9; } .box { background: #8ec63f; height: 100px; float: left; margin: 10px; width: 200px; }
一個解決方法是在父容器閉合標簽前加上一個空元素,並且設置它的clear : both。“清除浮動元素”這一招可以解決大多數情況,但是它並不是“語義正確”的。隨着頁面上需要清除的浮動元素 的數量增加,需要的空節點的數量也隨之增加,但是這些空節點並沒有任何的HTML語義。
幸運的是,有一些其他技巧同樣使用,最著名的就是使用overflow和clearfix的技巧。
使用overflow
在父容器上設置 overflow:auto 可以讓它自動包含子元素,從而具有了實際的height值,這樣上例中的灰色背景將得到顯示。
在IE6中使用這一招時需要給父節點容器設置height或者width屬性。因為實際情況中height常常是可變的,所以是設置width的值。對於蘋果平台上的IE,設置overflow:auto將會給容器增加滾動條,所以最好是設置 overflow : hidden 。
.box-set { background: #404853; overflow: auto; }
這一招有些副作用。例如,需要增加樣式或者移動子元素超出了父容器的范圍時,比如實現邊框陰影或者加上一個下拉菜單。在下面的例子中你將看到,當邊框陰影超出父容器的范圍時就會被遮蓋了,同時第二個子元素排列有問題。
使用clearfix
clearfix通常搭配 :before 或者 :after 偽元素使用。使用偽元素就是在包含浮動元素的父容器的前面或者后面創造一個隱藏的元素。通過對 :before 偽元素使用 display:table 來創建一個匿名的table-cell元素,從而防止子元素的top margin消失。這一招在IE6和7中具有一致的效果。同樣的,通過設置 :after 偽元素來防止子元素的bottom margin消失。
另外,需要對父容器使用 *zoom 屬性觸發hasLayout機制來解決IE6和7的一致性。hasLayout機制決定了元素應該怎樣渲染和框住它的內容,以及元素間的位置關系。
在下面使用clearfix的例子中,你將看到元素就算超出了父容器也可以顯示了。(注意邊框陰影)
.box-set:before, .box-set:after { content: ""; display: table; } .box-set:after { clear: both; } .box-set { *zoom: 1; }
有效地包含浮動元素
具體使用哪一個技巧取決於你的個人習慣。有些人傾向於使用clearfix技巧,因為它在跨瀏覽器上的一致性更好。另一些人覺得clearfix需要更多的代碼。因此,選擇哪個技巧不重要,重要的是注釋注明和寫進文檔。
一個常見的實現就是給所有需要包含浮動元素的父容器一個統一的類名,方便管理樣式。比如使用下列代碼,這樣只需給需要包含浮動元素的父節點加上 group的類名即可。
.group:before, .group:after { content: ""; display: table; } .group:after { clear: both; } .group { *zoom: 1; }
Position屬性
有些情況下,你需要更多的對元素位置的控制,這時候就需要使用position屬性了。position屬性一共有五種不同的取值。
Position Static
這是position屬性的默認取值,意味着這個元素沒有也不接受任何對於該元素的位置偏移量屬性。
在下列的例子中,所有的盒子都將一個接一個的堆起來。因為它們都是塊級元素,並且沒有被浮動。
<div class="box-set"> <div class="box box-1">Box 1</div> <div class="box box-2">Box 2</div> <div class="box box-3">Box 3</div> <div class="box box-4">Box 4</div> </div>
.box-set { background: #e8eae9; } .box { background: #8ec63f; height: 80px; width: 80px; }
Position Relative
relative定位非常相識於static定位。最大的區別就是相對定位的元素可以使用偏移量:top, right, bottom, left。這四個偏移量可以讓元素朝任何方向移動,從而精確的控制顯示出來的位置。
注意,盡管相對定位的元素可以使用偏移量屬性,但是它在網頁排版時按照的卻是跟static position相同的方式(這點區別於fixed position和absolute position)。另外,相對定位的元素可以覆蓋其它元素,或者被其它元素覆蓋,盡管它自身並沒有偏移。
在下列的例子中,所有的盒子都是一個接一個的堆起來。但是他們按照各自被定義的offset相對於原本的位置做了改變。所以,有些盒子覆蓋了其他的盒子,而不是推開其他盒子。如果一個元素是相對定位(甚至它還做了偏移),它周圍的元素在排版時參考的依然是那個元素原本的位置(指在沒有偏移時的位置)。
<div class="box-set"> <div class="box box-1">Box 1</div> <div class="box box-2">Box 2</div> <div class="box box-3">Box 3</div> <div class="box box-4">Box 4</div> </div>
.box-set { background: #e8eae9; } .box { background: #8ec63f; height: 80px; position: relative; width: 80px; } .box-1 { top: 20px; } .box-2 { left: 40px; } .box-3 { bottom: -10px; right: 20px; }
如果同時聲明top和bottom的值,那么top值的優先級更高。如果同時聲明left和right的值,那么優先級取決於網頁的語言(例如,英語法語德語西班牙語)。比如,在英語的網頁中,left的優先級更高;在阿拉伯語的網頁中,right的優先級更高。
Position Absolute
絕對定位的元素接受偏移量。在排版中,絕對定位的元素從原來的位置上被抹去了(因此它后面的元素將占領它目前的位置),然后根據它的相對定位的父節點的位置定位。如果它沒有相對定位的父節點,那么元素直接參考body容器定位。
對絕對定位的元素使用偏移量屬性,這個元素將以相對定位的父節點作為參考系進行偏移。
如果沒有對絕對定位的元素使用偏移量屬性,那么該元素將被放置在父節點的左上角。如果只設置了top屬性,那么該元素則只做垂直方向的偏移,而水平方向依然靠着父節點的最左邊。
在下面的例子中,所有的盒子相對於父容器作了絕對定位。如果偏移量是正數,那么盒子被“往里推”了;如果偏移量是負數,那么盒子被“往外拉”了。
<div class="box-set"> <div class="box box-1">Box 1</div> <div class="box box-2">Box 2</div> <div class="box box-3">Box 3</div> <div class="box box-4">Box 4</div> </div>
.box-set { background: #e8eae9; height: 200px; position: relative; } .box { background: #8ec63f; height: 80px; position: absolute; width: 80px; } .box-1 { top: 6%; left: 2%; } .box-2 { top: 0; right: -40px; } .box-3 { bottom: -10px; right: 20px; } .box-4 { bottom: 0; }
如果絕對定位的元素有固定的height和width值:
如果同時聲明top和bottom的值,那么top值的優先級更高。如果同時聲明left和right的值,那么優先級取決於網頁的語言(例如,英語法語德語西班牙語)。比如,在英語的網頁中,left的優先級更高;在阿拉伯語的網頁中,right的優先級更高。
如果絕對定位的元素沒有固定的height或者width值:
如果元素並沒有固定height值,可是卻同時有top和bottom的值,那么該元素將橫跨除了top和bottom之外剩下的所有高度。同理,如果元素並沒有固定width值,可是同時有left和right的值,那么該元素將橫跨除了left和right之外剩下的所有寬度。如果元素既沒有固定height和width值,卻同時有top, bottom, left, right值,那么該元素將占據除了四條邊距離之外的所有空間。
Position Fixed
固定定位的元素跟絕對定位的元素很相似,只不過它參照的坐標系是瀏覽器的視口(viewport)。固定定位的元素不隨着頁面滾動而移動,它會始終保持在那個位置。另外,在IE6中使用固定定位有一個BUG,需要使用一些hack來解決。
一個典型的使用固定定位的例子是網頁中的頂部橫條或者底部橫條。當用戶滾動頁面時,那個橫條始終停留在瀏覽器視口的頂部或者底部。
<footer>Fixed Footer</footer>
footer { bottom: 0; left: 0; position: fixed; right: 0; }
z-index 屬性
網頁是一個二維空間,根據x軸和y軸展示各個元素。可是,如果你需要讓某個元素放置在其他元素的上面(可在默認的排版中,她並不是在他的上面),這時你可以改變她的z-index屬性,讓她跑到他的上面。
元素在z軸的位置的位置取決於它在DOM中出現的先后順序。如果兩個元素發生重疊,先在DOM中出現的元素通常排在后出現元素的下面。改變先出現元素的z-index屬性是一個簡單的方法讓他出現在更上面。擁有最高z-index屬性的元素永遠被排在最上面,與它在DOM樹中的位置無關。
如果你需要設置一個元素的z-index屬性,你必須首先設置這個元素是relative,absolute或者fixed定位。就像對於設置top, bottom, left, right屬性一樣。
<div class="box-set"> <div class="box box-1">Box 1</div> <div class="box box-2">Box 2</div> <div class="box box-3">Box 3</div> <div class="box box-4">Box 4</div> </div>
.box-set { background: #e8eae9; height: 160px; position: relative; } .box { background: #8ec63f; border: 3px solid #f7941d; position: absolute; } .box-1 { left: 10px; top: 10px; } .box-2 { bottom: 10px; left: 70px; z-index: 3; } .box-3 { left: 130px; top: 10px; z-index: 2; } .box-4 { bottom: 10px; left: 190px; z-index: 1; }