css-佈局
一,BFC自適應佈局
1,BFC含義
BFC(Block formatting context)直譯為"塊級格式化上下文"。它是一個獨立的渲染區域,只有Block-level box參與, 它規定了內部的Block-level Box如何佈局,並且與這個區域外部毫不相干。
2,BFC 作用:
1. 利用 BFC 避免外邊距摺疊
2. 清除內部浮動 (撐開高度)
原理: 觸發父 div 的 BFC 屬性,使下面的子 div 都處在父 div 的同一個 BFC 區域之內
3. 避免文字環繞
4. 分屬於不同的 BFC 時,可以阻止 margin 重疊
5. 多列布局中使用 BFC
3,如何生成 BFC:(脫離文件流,滿足下列的任意一個或多個條件即可)
1. 根元素,即 HTML 元素(最大的一個 BFC)
2. float 的值不為 none
3. position 的值為 absolute 或 fixed
4. overflow 的值不為 visible(預設值。內容不會被修剪,會呈現在元素框之外)
5. display 的值為 inline-block、table-cell、table-caption
4,BFC 佈局規則:
1. 內部的 Box 會在垂直方向,一個接一個地放置。
2. 屬於同一個 BFC 的兩個相鄰的 Box 的 margin 會發生重疊
3. BFC 就是頁面上的一個隔離的獨立容器,容器裡面的子元素不會影響到外面的元素。反之也如此, 文字環繞效果,設定 float
5. 計算 BFC 的高度,浮動元素也參與計算
例子1(利用BFC避免margin重疊)
<!DOCTYPE html> <html lang="en"> <head> <title>防止margin重疊</title> </head> <style> *{ margin: 0; padding: 0; } div { color: #f55; background: #eaf886; width: 200px; line-height: 100px; text-align:center; margin: 30px; } </style> <body> <div>box1</div> <div>box2</div> </body> </html>
可以看到,屬於同一個BFC的兩個相鄰的Box會發生margin重疊,所以我們可以設定,兩個不同的BFC,也就是我們可以把第二個div啟用成為一個BFC,分屬於不同的 BFC 時,可以阻止 margin 重疊
<!DOCTYPE html>
<html lang="en">
<head>
<title>防止margin重疊</title>
</head>
<style>
*{
margin: 0;
padding: 0;
}
div{
color: #f55;
background: #eaf886;
width: 200px;
line-height: 100px;
text-align:center;
margin: 30px;
}
div:nth-child(2){
position:absolute /*啟用成BFC*/
}
</style>
<body>
<div>box1</div>
<div>box2</div>
</body>
</html>
BFC兩欄佈局
<!DOCTYPE html> <html lang="en"> <head> <title>BFC兩欄佈局</title> </head> <style> *{ margin: 0; padding: 0; } body { width: 100%; position: relative; } .left { width: 100px; height: 250px; float: left; background: rgb(139, 214, 78); text-align: center; line-height: 300px; font-size: 20px; } .right { overflow: hidden; height: 300px; background: rgb(170, 54, 236); text-align: center; line-height: 300px; font-size: 40px; } </style> <body> <div class="left">left</div> <div class="right">right</div> </body> </html>
關鍵:讓右側塊變為BFC,因為BFC元素不與Float元素相重疊,如果去掉右側 overflow:hidden,則如圖下:
二,浮動佈局
<!DOCTYPE html> <html lang="en"> <head> <title>Document</title> <style> * { padding: 0; margin: 0; } .left, .right, .center { min-height: 100px; } .left { background-color: red; width: 200px; float: left; } .right { background-color: blue; width: 200px; float: right; } .center { background-color: orange; width: 100%; } </style> </head> <body> <aside class="left"></aside> <aside class="right"></aside> <main class="center"> <h1>浮動解決方案</h1> <p>方法:left和right寫在center前面,並且分別左右浮動,中間的這個div因為是塊級元素,所以在水平方向上按照他的包容塊自動撐開</p> </main> </body> </html>
這種佈局方式,dom 結構必須是先寫浮動部分,然後再中間塊,否則右浮動塊會掉到下一行。 浮動佈局的優點就是比較簡單,相容性也比較好。但浮動佈局是有侷限性的,浮動元素脫離文件流,要做清除浮動,這個處理不好的話,會帶來很多問題,比如父容器高度塌陷等。
三,絕對定位佈局
<!DOCTYPE html> <html lang="en"> <head> <title>絕對定位三欄佈局</title> <style> * { margin: 0; padding: 0; } aside { position: absolute; width: 300px; min-height: 100px; } aside.left { left: 0; background-color: red; } aside.right { right: 0; background-color: blue; } main.center { position: absolute; left: 300px; right: 300px; background-color: orange; } </style> </head> <body> <aside class="left"></aside> <aside class="right"></aside> <main class="center"> <h1>絕對定位解決方案</h1> <p>左右區域分別postion:absolute,固定到左右兩邊</p> <p>中間區域postion:absolute;left:300px; right: 300px</p> </main> </body> </html>
絕對定位佈局優點就是快捷,設定很方便,而且也不容易出問題。缺點就是,容器脫離了文件流,後代元素也脫離了文件流,高度未知的時候,會有問題,這就導致了這種方法的有效性和可使用性是比較差的。
四,flexbox佈局
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta http-equiv="X-UA-Compatible" content="ie=edge" /> <title>Document</title> <style> * { margin: 0; padding: 0; } .left, .right, .center { min-height: 100px; } .wrapper { display: flex; } .left { background-color: red; width: 300px; } .center { background-color: orange; flex: 1; } .right { background-color: blue; width: 300px; } </style> </head> <body> <div class="wrapper"> <aside class="left"></aside> <main class="center"> <h1>flex佈局解決方案</h1> <p>包裹這個3個塊的父元素display: flex; 中間的元素flex: 1;</p> </main> <aside class="right"></aside> </div> </body> </html>
flexbox 佈局是 css3 裡新出的一個,它就是為了解決上述兩種方式的不足出現的,是比較完美的一個。目前移動端的佈局也都是用 flexbox。 flexbox 的缺點就是 IE10 開始支援,但是 IE10 的是-ms 形式的。
五,表格佈局
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta http-equiv="X-UA-Compatible" content="ie=edge" /> <title>表格佈局</title> <style> * { margin: 0; padding: 0; } .wrapper { display: table; width: 100%; } .left, .right, .center { min-height: 100px; display: table-cell; } .left { width: 300px; background-color: red; } .center { background-color: orange; } .right { background-color: blue; width: 300px; } </style> </head> <body> <div class="wrapper"> <aside class="left"></aside> <main class="center"> <h1>表格佈局</h1> <p>父元素display: table;並且寬度為100%</p> <p>每一個子元素display: table-cell;</p> <p>左右兩側新增寬度,中間不加寬度</p> </main> <aside class="right"></aside> </div> </body> </html>
表格佈局的相容性很好,在 flex 佈局不相容的時候,可以嘗試表格佈局。當內容溢位時會自動撐開父元素。
表格佈局也是有缺陷:① 無法設定欄邊距;② 對 seo 不友好;③ 當其中一個單元格高度超出的時候,兩側的單元格也是會跟著一起變高的,然而有時候這並不是我們想要的效果。
六,網格佈局
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta http-equiv="X-UA-Compatible" content="ie=edge" /> <title>網格佈局</title> <style> * { margin: 0; padding: 0; } /* 網格佈局 */ .wrapper { display: grid; width: 100%; grid-template-columns: 300px 1fr 300px; } .left { background-color: red; } .center { background-color: orange; } .right { background-color: blue; } </style> </head> <body> <div class="wrapper"> <aside class="left"></aside> <main class="center"> <h1>網格佈局</h1> <p>父元素display: grid;並且寬度為100%</p> <p>grid-template-columns中指定每列的寬度</p> </main> <aside class="right"></aside> </div> </body> </html>
CSS Grid 是建立網格佈局最強大和最簡單的工具。就像表格一樣,網格佈局可以讓 Web 設計師根據元素按列或行對齊排列,但他和表格不同,網格佈局沒有內容結構,從而使各種佈局不可能與表格一樣。例如,一個網格佈局中的子元素都可以定位自己的位置,這樣他們可以重疊和類似元素定位。
但網格佈局的相容性不好。IE10+上支援,而且也僅支援部分屬性。
七,聖盃佈局
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>實現三欄水平佈局之聖盃佈局</title> <style type="text/css"> .container { padding-left: 150px; padding-right: 150px; } .left { float: left; width: 150px; height: 100px; background: red; margin-left: -100%; position: relative; left: -150px; } .center { float: left; width: 100%; height: 200px; background: yellow; position:relative } .right { float: left; width: 150px; height: 100px; background: blue; margin-left: -150px; position: relative; right: -150px; } </style> </head> <body> <article class="container"> <div class="center"> <h2>聖盃佈局</h2> </div> <div class="left"></div> <div class="right"></div> </article> </body> </html>
實現步驟:
①三個部分都設定為左浮動,否則左右兩邊內容上不去,就不可能與中間列同一行。然後設定 center 的寬度為 100%(實現中間列內容自適應),此時,left 和 right 部分會跳到下一行
②通過設定 margin-left 為負值讓 left 和 right 部分回到與 center 部分同一行
③通過設定父容器的 padding-left 和 padding-right,讓左右兩邊留出間隙。
④通過設定相對定位,讓 left 和 right 部分移動到兩邊
特點:
比較特殊的三欄佈局,同樣也是兩邊固定寬度,中間自適應,唯一區別是 dom 結構必須是先寫中間列部分,這樣實現中間列可以優先載入。
缺點:
center 部分的最小寬度不能小於 left 部分的寬度,否則會 left 部分掉到下一行
如果其中一列內容高度拉長,其他兩列的背景並不會自動填充。
八,雙飛翼佈局
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>雙飛翼佈局</title> <style type="text/css"> .container { min-width: 600px; } .left { float: left; width: 200px; height: 200px; background: red; margin-left: -100%; } .center { float: left; width: 100%; height: 300px; background: yellow; } .center .inner { margin: 0 200px; /*新增部分*/ } .right { float: left; width: 200px; height: 200px; background: blue; margin-left: -200px; } </style> </head> <body> <article class="container"> <div class="center"> <div class="inner">雙飛翼佈局</div> </div> <div class="left"></div> <div class="right"></div> </article> </body> </html>
實現步驟(前兩步與聖盃佈局一樣)
1 三個部分都設定為左浮動,然後設定 center 的寬度為 100%,此時,left 和 right 部分會跳到下一行;
2 通過設定 margin-left 為負值讓 left 和 right 部分回到與 center 部分同一行;
3 center 部分增加一個內層 div,並設 margin: 0 200px;
特點
同樣也是三欄佈局,在聖盃佈局基礎上進一步優化,解決了聖盃佈局錯亂問題,實現了內容與佈局的分離。而且任何一欄都可以是最高欄,不會出問題
缺點
多加一層 dom 樹節點,增加渲染樹生成的計算量