CSS定位與佈局
我們在編寫網頁程式碼時,首先應該做的就是設計好頁面的佈局形式,然後再往裡面填充內容。網頁佈局的好與壞,直接決定了網頁最終的展示效果。PC端常見的網頁佈局形式有兩列布局、三列布局等。在CSS中,我們通常使用浮動(float)、定位(position)、顯示模式(display)相關屬性結合使用,以達到預期效果。
一 文件流
文件流就是HTML文件內所有元素按照一定規律排列並顯示的形式。
CSS文件流大致可以分為3種:標準流,浮動流,定位流。
1,標準流
預設情況下,HTML元素都在標準流中呈現和展示。我們之前把元素分為塊級元素,行內元素,行內塊級元素,他們的特性是塊級獨佔一行,行內和行內塊級可以在一行內共存,這些特性都是針對標準流的。總結一下就是,標準流中元素只能在水平或垂直方向上排版。如果元素是塊級元素, 那麼就會垂直排版,如果元素是行內元素/行內塊級元素, 那麼就會水平排版。
2,浮動流
浮動流只有一種排版方式, 就是水平排版。 它只能設定某個元素在父元素內左對齊或者右對齊。設定了浮動的元素,將脫離標準流,之後它將無視元素的display屬性,並且都被當做塊級元素處理。
1 div{ 2 float:left;/*規定元素向左浮動*/ 3 /*float:right;規定元素向右浮動*/ 4 }
請注意,浮動float屬性沒有center取值,並且,如果設定了浮動屬性,那麼你將不能通過使用margin:0 auto;屬性使元素居中。
3,定位流
標準流和浮動流都只能在水平或垂直方向佈局元素,但現實是,我們可能需要在上下左右幾個方向上同時偏移元素,定位流正是為了解決這一問題而設計的。通過設定元素的position屬性,可以讓元素處於定為流中,並通過left、right、top、bottom屬性設定元素具體的偏移量。
定為流分為四種:
a) static 靜態定位,實際上所有元素預設都是靜態定位的,即處於標準流中。
b) relative 相對定位,元素保留在標準流中所佔用的位置,但實際是邊框及以內的部分將顯示在偏移之後的位置。即雖然元素已經不再原來的位置了,但之前所佔用的空間並不會被釋放給其他標準流中的元素。
c) absolute 絕對定位,元素脫離標準流,瀏覽器把它視作塊級元素,不論定位之前它是何種元素,其他元素也將無視它。絕對定位的偏移量是相對於其有定位屬性的第一個祖先元素的。
d) fixed 固定定位,固定定位和絕對定位相似,但它的偏移量固定的相對於瀏覽器視窗。
二 浮動
當某個元素浮動之後,相當於從標準流中刪除了該元素,標準流中的元素將會無視浮動元素,並且可能被浮動元素覆蓋。
當有多個元素浮動時,他們有以下特點:
a) 在相同方向上浮動的元素,先浮動的元素會顯示在前面。
1 .brother1{ 2 float:left; 3 } 4 .brother2{ 5 float:left; 6 } 7 /*brother1將顯示在brother2的左邊,如果都設定右浮動,那麼brother1將顯示在brother2的右邊*/
b) 不同方向的浮動元素,會盡量去尋找並貼靠前面和它浮動方向相同的元素。如果前面沒有其他浮動元素,那麼它將緊貼其父元素的邊界。
1 .son1{ 2 float:left; 3 } 4 .son2{ 5 float:right; 6 } 7 .son3{ 8 float:left; 9 } 10 /*son1和son3會在父元素的左側顯示,並且son3緊跟在son1的後面。son2則在父元素的右側顯示,緊貼父元素上*/
c) 如果有未浮動的兄弟元素,那麼元素在浮動之後,會根據它在標準流中的位置確定該在第幾行展示。
1 .brother1{ 2 background-color:red; 3 float:left; 4 } 5 .brother2{ 6 background-color:blue; 7 } 8 .brother3{ 9 background-color:yellow; 10 float:left; 11 } 12 /*最終效果是:brother1和brother2在第一行顯示,但brother1蓋住了brother2,brother3單獨在第二行顯示*/
浮動元素還有一個特點:浮動元素不會擋住沒有浮動元素中的文字, 沒有浮動的文字會自動給浮動的元素讓位置。這才是設計浮動的初衷。
元素浮動後會帶來兩個問題,第一個是造成父元素的高度塌陷,padding和margin無效。第二個是被其他元素無視,出現元素相互覆蓋的現象。那麼要怎樣才能消除浮動對其他元素的影響呢?我們通過下面的方式清除浮動帶來的影響。
a) 為父元素設定固定的高度(解決問題一)。
1 father{ 2 heigth:100px; 3 } 4 son{ 5 float:left; 6 }
b) 為父元素設定浮動(解決問題一)。
1 father{ 2 float:left; 3 } 4 son{ 5 float:left; 6 }
c) 設定clear屬性。clear屬性的功能是使浮動元素不去尋找相鄰的其他浮動元素,從而消除浮動元素對其他元素的影響(解決問題二)。
1 father::after{ 2 content:''; 3 display:block; 4 height:0; 5 clear:both; 6 } 7 /*俗稱隔牆法,根據需要也可以設定在浮動元素自身或其父元素上*/ 8 son{ 9 float:left; 10 }
d) 為父元素設定overflow:hidden;屬性(解決問題二)。
1 father{ 2 overflow:hidden; 3 } 4 /*原理是觸發BFC機制*/ 5 son{ 6 float:left; 7 }
三 定位
1,相對定位
通過給元素設定position:relative;屬性設定元素相對定位。
1 .box{ 2 position:relative; 3 top:50px; 4 left:50px; 5 } 6 /*box元素將在原來的位置向下和向右偏移50px,請注意:在定位流中,同一個方向上的定位屬性只能使用一次*/
請注意在瀏覽器中的座標系和一般座標系並不相同。如果不清楚請看《CSS基礎》第4.3節。
在相對定位中,實際上元素並未脫離標準流,所以瀏覽器還是會區分它是否是塊級或其他型別的元素。另外,設定元素的margin屬性,實際上margin區域會出現在元素定位之前的位置。
2,絕對定位
通過給元素設定position:absolute;屬性設定元素絕對定位。
1 .box{ 2 position:absolute; 3 top:50px; 4 left:50px; 5 } 6 /*box元素將相對於父元素的左頂點(座標原點)向下向右偏移50px*/
如果沒有設定偏移量,預設top和left偏移量為0。如果元素所有祖先元素都沒有定位屬性,那麼元素將相對body元素偏移。
在使用絕對定位時有兩個注意點:第一個是如果網頁寬高較大時(大於瀏覽器可視區寬高),並且元素最終相對於body定位了,實際上它只是相對瀏覽器首屏的寬高進行偏移,而不是整個網頁的寬高。第二個是絕對定位的元素會自動忽略有定位屬性的祖先元素的padding屬性。
絕對定位一般和相對定位配合使用,父元素設定相對定位,但不設定偏移量(預設為0),子元素設定絕對定位,這樣就可以把子元素的偏移控制在父元素之內。
1 .father{ 2 position:relative; 3 } 4 .son{ 5 position:absolute; 6 left:50px; 7 top:50px; 8 } 9 /*子元素相對父元素進行偏移,二父元素不受影響*/
3,固定定位
元素的固定定位和背景圖片的關聯性相似,可以控制元素是否隨著滾動條滾動。
1 div{ 2 position:fixed; 3 top:100px; 4 left:50px; 5 }
固定定位的元素相對於瀏覽器視口偏移,和絕對定位的元素一樣,它會脫離標準文件流,並且瀏覽器把他們一致視作塊級元素。
4,z-index屬性
預設情況下,所有元素都有一個z-index屬性,用於定義它們的覆蓋關係。
1 div{ 2 z-index:999; 3 }
通常情況下,元素的z-index屬性值都是0,並且定位流中的元素會覆蓋標準流中的元素,同在定位流中的元素,寫在後面的會覆蓋寫在前面的元素。
在定為流中,如果你想調整它們的覆蓋關係,你可以設定它們的z-index屬性,並且誰的值越大,顯示優先順序越高。
需要注意的是,如果定位元素的父元素也設定了z-index屬性,那麼子元素的z-index屬性將失效,並且最終是根據父元素的z-index屬性來判斷覆蓋關係。
四 居中與flex
1,水平居中
如果元素是文字、圖片等行內元素,在父元素中設定text-align:center即可實現行內元素水平居中,如果子元素是不定寬塊級元素,將子元素的display設定為inline-block,使子元素變成行內元素,可以實現塊級元素的水平居中。
1 p{ 2 text-align:center; 3 /*文字圖片等水平居中*/ 4 } 5 .father{ 6 text-align:center; 7 } 8 .son{ 9 display:inlin-block; 10 /*不定寬塊級元素,修改顯示模式,利用text-align屬性使其居中*/ 11 }
如果子元素是定寬塊級元素,又不想改變顯示模式,那麼可以通過設定margin屬性實現水平居中。
1 div{ 2 width:500px; 3 height:300px; 4 margin:0 auto; 5 /*auto,讓瀏覽器決定*/ 6 }
2,垂直居中
首先,如果父元素高度一定,子元素是文字或圖片等高度由內容撐開的行內元素,可以使用line-height屬性讓其垂直居中。
1 .father{ 2 height:100px; 3 } 4 .son{ 5 font-size:20px; 6 line-height:100px; 7 }
如果子元素是不定高度的塊級元素,我們則可以通過給父元素設定display:table-cell;和vertical-align:middle;屬性來解決。
1 .father{ 2 height:100px; 3 display:table-cell; 4 vertical-align:middle; 5 } 6 .son{ 7 display:block; 8 height:?; 9 }
10 /*這樣實現垂直居中的原理是:使父元素以表格的形式呈現,再利用vertical-align屬性在表格中是設定單元格內容垂直對齊方式的特性,從而達到塊級元素垂直居中的效果。*/
需要注意的是:設定了dispaly:table-cell屬性後,元素將忽略margin值。並且,如果你還設定了絕對定位或浮動,該屬性功能將被破壞。
如果子元素是定高的,那麼你只需簡單的使用margin屬性,即可達到讓元素垂直居中的目的。
1 .father{ 2 height:200px; 3 } 4 .son{ 5 height:100px; 6 margin-top:50px 7 }
3,水平垂直居中
通過上面的方式組合使用,即可達到元素水平垂直都居中的效果。
1 .father{ 2 width:800px; 3 height:600px; 4 text-align:center; 5 } 6 .son{ 7 width:600px; 8 heigth:400px; 9 margin:100px auto; 10 }
或者使用絕對定位+相對定位。
1 .father{ 2 width:600px; 3 height:800px; 4 position:relative; 5 } 6 .son{ 7 width:400px; 8 height:600px; 9 position:absolute; 10 top:100px; 11 left:100px; 12 }
4,flex
flex即彈性佈局,用來為盒狀模型提供最大的靈活性。需要注意的是,元素使用flex佈局後,float,clear和vertical-align屬性將失效。flex是display(顯示模式)屬性的一個可選值,而不是position(定位)。
1 .box{ 2 display:flex; 3 /*為塊級元素設定彈性佈局*/ 4 } 5 .inline-box{ 6 display:inline-box; 7 /*為行內元素設定彈性佈局*/ 8 }
設定了彈性佈局的盒子我們稱為彈性盒子(flex box),或者把它稱作容器(container)。如果把一個彈性盒子看成一個完整的工程(project),那麼我們可以把彈性盒子內部的元素看做是單個的模組專案(module item),這些模組都會遵守彈性盒子的規範,通過設定一些屬性,自動的調整自身的大小以適應彈性盒子中可用空間的變化。
彈性盒子中預設有兩根軸線,水平方向的主軸,垂直方向的縱軸(交叉軸)。軸線與盒子邊框的交點是開始位置和結束位置。
容器屬性:
1 .box{ 2 display:flex; 3 flex-direction:row; 4 /*該屬性決定主軸的方向,即專案排列的方向。row,預設值,橫向從左至右;colum,縱向從上至下展示項;row-reverse和row方向相反,colum-reverse和colum方向相反*/ 5 flex-wrap:nowrap; 6 /*該屬性定義如果一條軸線排不下,如何換行。nowrap,預設值,不換行;wrap,換行*/ 7 justify-content:flex-start; 8 /*該屬性定義專案在主軸上的對齊方式。flex-start,預設值,開始對齊(例如上面設定了橫向從左至右排列專案,則這裡表示左對齊,如果上面設定row-reverse,則這裡表示右對齊),該屬性還有幾個可選值:flex-end,結束對齊;center,居中對齊;space-between,兩端對齊;space-around,專案間隔相等*/ 9 align-items:stretch; 10 /*該屬性定義專案在交叉軸上的對齊方式。stretch,預設值,如果專案沒有具體高度,將佔滿整個容器;center,專案中線對齊;flex-start,開始對齊;flex-end,結束對齊;baseline,各專案的第一行文字基線對齊*/ 11 }
要想專案自動的調整自身的大小以適應彈性盒子中可用空間的變化,還需要依賴專案自身的一些屬性。
1 .item{ 2 order:1; 3 /*設定專案排列的先後順序,數字越大越靠後,如果沒收設定,則誰寫在前面誰就排在前面。*/ 4 flex-grow:1; 5 /*定義可以放大的比例,預設是0,表示不放大,1表示放大1倍,2表示放大2倍,以此類推。如果所有專案都設定成相同數字,那麼容器的可用空間會被專案等分。*/ 6 flex-shrink:1; 7 /*定義可以縮小的比例,預設是1,表示可以縮小1倍,2表示縮小2倍,以此類推。0表示不縮小。如果所有專案都設定成相同數字,那麼容器的可用空間會被專案等分。*/ 8 flex-basis:auto; 9 /*定義專案佔用主軸的長度,可以是width或height屬性一樣的值。比如百分比,px,em等。兩個特殊值:auto(預設的)表示佔用盒子本來的大小;0則表示只佔專案內容區域的大小()*/ 10 }
縮放和尺寸可以使用縮寫形式。
1 .item{ 2 flex:1 1 auto; 3 /*分別表示flex-grow,flex-shrink,flex-basis*/ 4 }
採用縮寫形式時需要注意,如果只有一個數字值,則代表flex-grow;如果只有一個寬度值(有單位的),則代表flex-basis;如果值有兩個值,那麼第一個必須是數字,代表flex-grow,第二個可以是數字或寬度,分表代表flex-shrink或flex-basis。
五 兩列布局
左側定寬右側自適應寬度的兩列布局常用方式有下面幾種:
1,左邊脫離標準流,右邊使用margin屬性使其偏移
1 .left{ 2 width:200px; 3 float:left; 4 /* 5 position:absolute; 6 left:0; 7 */ 8 } 9 .right{ 10 margin-left:200px 11 }
2,calc()
1 .left{ 2 width:200px; 3 display:inline-block; 4 } 5 .right{ 6 display:inline-block; 7 width:calc(100% - 200px); 8 } 9 /*另一種形式是,左右均浮動,然後利用calc()動態計算右邊的寬度*/
3,float+BFC
1 .left{ 2 width:200px; 3 float:left; 4 } 5 .right{ 6 overflow: auto; 7 } 8 /*左側浮動,但是右側盒子通過overflow: auto;形成BFC,使右側盒子不會無視浮動的元素*/
4,flex
1 .wrap{ 2 display:flex; 3 aligin:items:flex-start; 4 } 5 .left{ 6 width:50px; 7 flex:0 0 auto; 8 } 9 .right{ 10 flex:1 1 auto; 11 }
六 三列布局
一般的3列布局要求是:中間自適應寬度,左右兩邊定寬。滿足這種要求的佈局我們一般有兩種方式,聖盃佈局和雙飛翼佈局。
1,聖盃佈局
HTML部分:
1 <div class='wrap'> 2 <div class="center">center</div> 3 <div class="left">left</div> 4 <div class="right">right</div> 5 </div>
CSS部分:
1 .wrap{ 2 width: 50%; 3 height:400px; 4 margin:50px auto; 5 position: relative; 6 } 7 .wrap .center{ 8 width: 100%; 9 height:400px; 10 float: left; 11 } 12 .wrap .left{ 13 width:100px; 14 height: 400px; 15 float: left; 16 margin-left: -100%; 17 position: relative; 18 left:-100px; 19 } 20 .wrap .right{ 21 height: 400px; 22 width:100px; 23 float: right; 24 margin-left: -100%; 25 position: relative; 26 right:-100px; 27 }
原理:左中右三塊均設定浮動,center寬度100%,left和right通過設定負margin值, 使其和center處於同一行,然後利用相對定位讓其分佈於center的兩邊。
2,雙飛翼佈局
HTML部分:
1 <div class='wrap'> 2 <div class="center"> 3 <div class="content"></div> 4 </div> 5 <div class="left">left</div> 6 <div class="right">right</div> 7 </div>
CSS部分:
1 .wrap{ 2 width: 50%; 3 height:400px; 4 margin:50px auto; 5 } 6 .wrap .center{ 7 width: 100%; 8 height:300px; 9 float: left; 10 } 11 .wrap .center .content{ 12 margin:0 100px; 13 } 14 .wrap .left{ 15 width: 100px; 16 height:300px; 17 float: left; 18 margin-left: -100%; 19 } 20 .wrap .right{ 21 width: 100px; 22 height:300px; 23 float: right; 24 margin-left: -100%; 25 }
原理:左中右三塊均設定浮動,center寬度100%,left和right通過設定負margin值,使其和center處於同一行,此時left和right實際上遮住了部分center,所以center中的content需要設定margin。
聖盃佈局和雙飛翼佈局的區別:除了HTML程式碼結構不同外,聖盃佈局的center寬度即為內容區寬度,left和right靠在其兩邊。雙飛翼佈局的center寬度等於內容區寬度加left和right寬度。因為它的left和right實際上佔用(遮住)了center的空間,所以需要在center中新增一個.content的div,並設定它的margin,以便空出left和right的位置。
聖盃佈局和雙飛翼佈局的好處是,center區域可以優先於左右兩邊被瀏覽器渲染。不過現代瀏覽器普遍效能良好,這點優先根本不易被使用者察覺到。
3,calc()
通過calc()函式我們也可以輕鬆滿足兩邊定寬,中間自適應的要求。
HTML部分:
1 <div class="wrap"> 2 <div class="left">left</div> 3 <div class="right">left</div> 4 <div class="center">center</div> 5 </div>
CSS部分:
1 .wrap{ 2 width:80%; 3 margin: 0 auto; 4 background-color: #ccc; 5 /*position: relative;*/ 6 } 7 8 .wrap .center{ 9 background-color: blue; 10 margin-left:200px; 11 width:calc(100% - 400px); 12 } 13 .wrap .left{ 14 background-color: red; 15 width:200px; 16 float:left; 17 /*position: absolute; 18 left: 0; 19 top:0;*/ 20 } 21 .wrap .right{ 22 background-color: yellow; 23 width:200px; 24 float:right; 25 /*position: absolute; 26 right: 0; 27 top:0;*/ 28 } 29 /*通過浮動和定位都可以實現兩邊固定的效果,需要注意的是,使用浮動需要把center區域放到left和right之後,原因請往上看浮動的第三個特徵*/
4,flex佈局
HTML部分同calc()。
CSS部分:
1 .wrap{ 2 width:80%; 3 margin: 0 auto; 4 background-color: #ccc; 5 display: flex; 6 flex-direction: row; 7 flex-wrap: nowrap; 8 } 9 10 .center{ 11 background-color: blue; 12 flex:1 0 auto; 13 order:1; 14 } 15 .left{ 16 background-color: red; 17 width:200px; 18 flex:0 0 auto; 19 order:0; 20 } 21 .right{ 22 background-color: yellow; 23 width:200px; 24 flex:0 0 auto; 25 order:2; 26 }
&n