1. 程式人生 > 實用技巧 >css-佈局

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

4. BFC 的區域不會與 float box 重疊。
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 樹節點,增加渲染樹生成的計算量