經(jīng)典布局詳解——圣杯布局、雙飛翼布局、Flex布局和絕對(duì)定位布局

題目要求:針對(duì)如下DOM結(jié)構(gòu),編寫CSS,實(shí)現(xiàn)三欄水平布局,其中l(wèi)eft、right分別位于左右兩側(cè),left寬度為200px,right寬度為300px,main處在中間,寬度自適應(yīng)。
要求:允許增加額外的DOM節(jié)點(diǎn),但不能修改現(xiàn)有節(jié)點(diǎn)順序。

<div class="container">
     <div class="main">main</div>
     <div class="left">left</div>
     <div class="right">right</div>
</div>

圣杯布局與雙飛翼布局針對(duì)的都是三列左右欄固定中間欄邊框自適應(yīng)的網(wǎng)頁布局(想象一下圣杯是主體是加上兩個(gè)耳朵;鳥兒是身體加上一對(duì)翅膀),圣杯布局是Kevin Cornell在2006年提出的一個(gè)布局模型概念,在國(guó)內(nèi)最早是由淘寶UED的工程師(傳說是玉伯)改進(jìn)并傳播開來,在中國(guó)也有叫法是雙飛翼布局,它的布局要求有幾點(diǎn):
(1)、三列布局,中間寬度自適應(yīng),兩邊定寬;
(2)、中間欄要在瀏覽器中優(yōu)先展示渲染;
(3)、允許任意列的高度最高;
可以看出我們題目的要求跟圣杯布局和雙飛翼布局要求一樣。
下面我們看看具體的實(shí)現(xiàn)方法。

方法一:圣杯布局

1.設(shè)置基本樣式

/*3.圣杯布局法*/
.left, .main, .right {
  min-height: 130px;
}
.left {
  background: green;
  width: 200px;
}
.main {
  background-color: blue;
}
.right {
  background-color: red;
  width: 300px;
}

為了高度保持一致給left main right都加上min-height:130px。


圖片1.png

2.圣杯布局是一種相對(duì)布局,首先設(shè)置父元素container的位置:

    .container {
        padding: 0 300px 0 200px;
    }

實(shí)現(xiàn)效果是左右分別空出200px和300px區(qū)域,效果如圖:


圖片2.png

3.將主體部分的三個(gè)子元素都設(shè)置左浮動(dòng)

.left, .main, .right {
  min-height: 130px;
  float: left;
}

出現(xiàn)了如下情況,怎么辦,別著急慢慢來:


圖片3.png

4.設(shè)置main寬度為width:100%,讓其單獨(dú)占滿一行

.main {
  background-color: blue;
  width: 100%;
}
圖片4.png

5.設(shè)置left和right 負(fù)的外邊距

我們的目標(biāo)是讓left、main、right依次并排,但是上圖中l(wèi)eft和right都是位于下一行,這里的技巧就是使用負(fù)的margin-left:

.left {
  margin-left: -100%;
  background-color: green;
  width: 200px;
}
.right {
  margin-left: -300px;
  background-color: red;
  width: 300px;
}

負(fù)的margin-left會(huì)讓元素沿文檔流向左移動(dòng),如果負(fù)的數(shù)值比較大就會(huì)一直移動(dòng)到上一行。關(guān)于負(fù)的margin的應(yīng)用也是博大精深,這里肯定是不能詳細(xì)介紹了。
  設(shè)置left部分的margin-left為-100%,就會(huì)使left向左移動(dòng)一整個(gè)行的寬度,由于left左邊是父元素的邊框,所以left繼續(xù)跳到上一行左移,一直移動(dòng)到上一行的開頭,并覆蓋了main部分(仔細(xì)觀察下圖,你會(huì)發(fā)現(xiàn)main里面的字“main”不見了,因?yàn)楸籰eft遮住了),left上移過后,right就會(huì)處于上一行的開頭位置,這時(shí)再設(shè)置right部分margin-left為負(fù)的寬度,right就會(huì)左移到上一行的末尾。


圖片5.png

6.接下來只要把left和right分別移動(dòng)到這兩個(gè)留白就可以了。可以使用相對(duì)定位移動(dòng) left和right部分。

.left, .main, .right {
  position: relative;
  min-height: 130px;
  float: left;
}
.left {
  left: -200px;
  margin-left: -100%;
  background: green;
  width: 200px;
}
.right {
  right: -300px;
  margin-left: -300px;
  background-color: red;
  width: 300px;
}
圖片6.png

至此,我們完成了三列中間自適應(yīng)的布局,也就是傳說中的圣杯布局。完整的代碼如下:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>實(shí)現(xiàn)三欄水平布局之圣杯布局</title>
    <style type="text/css">
    .container {
        padding: 0 300px 0 200px;
    }
    .left, .main, .right {
        position: relative;
        min-height: 130px;
        float: left;
    }
    .left {
        left: -200px;
        margin-left: -100%;
        background: green;
        width: 200px;
    }
    .right {
        right: -300px;
        margin-left: -300px;
        background-color: red;
        width: 300px;
    }
    .main {
        background-color: blue;
        width: 100%;
    }
    </style>
</head>
<body>
<div class="container"> 
  <div class="main">main</div> 
  <div class="left">left</div> 
  <div class="right">right</div> 
</div>
</body>
</html>

方法二:雙飛翼布局

圣杯布局和雙飛翼布局解決問題的方案在前一半是相同的,也就是三欄全部float浮動(dòng),但左右兩欄加上負(fù)margin讓其跟中間欄div并排,以形成三欄布局。不同在于解決 “中間欄div內(nèi)容不被遮擋”問題的思路不一樣。
  他的HTML結(jié)構(gòu)發(fā)生了變化:

<div class="container"> 
  <div class="main">
      <div class="content">main</div> 
    </div>
  <div class="left">left</div> 
  <div class="right">right</div> 
</div>

直接貼出代碼,讀者可以自行參透他們的異同:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>實(shí)現(xiàn)三欄水平布局之雙飛翼布局</title>
    <style type="text/css">
    .left, .main, .right {
        float: left;
        min-height: 130px;
        text-align: center;
    }
    .left {
        margin-left: -100%;
        background: green;
        width: 200px;
    }

    .right {
        margin-left: -300px;
        background-color: red;
        width: 300px;
    }
    .main {
        background-color: blue;
        width: 100%;
    }
    .content{
        margin: 0 300px 0 200px;
    }
    </style>
</head>
<body>
<div class="container"> 
  <div class="main">
      <div class="content">main</div> 
    </div>
  <div class="left">left</div> 
  <div class="right">right</div> 
</div>
</body>
</html>

雙飛翼布局比圣杯布局多使用了1個(gè)div,少用大致4個(gè)css屬性(圣杯布局container的 padding-left和padding-right這2個(gè)屬性,加上左右兩個(gè)div用相對(duì)布局position: relative及對(duì)應(yīng)的right和left共4個(gè)屬性,;而雙飛翼布局子div里用margin-left和margin-right共2個(gè)屬性,比圣杯布局思路更直接和簡(jiǎn)潔一點(diǎn)。簡(jiǎn)單說起來就是:雙飛翼布局比圣杯布局多創(chuàng)建了一個(gè)div,但不用相對(duì)布局了。

方法三:Flex布局

Flex 是 Flexible Box 的縮寫,意為”彈性布局”,用來為盒狀模型提供最大的靈活性。
任何一個(gè)容器都可以指定為 Flex 布局,所以Flex 布局將成為未來布局的首選方案。

本實(shí)例的HTML結(jié)構(gòu)代碼如下:

<div class="container"> 
  <div class="main">main</div> 
  <div class="left">left</div> 
  <div class="right">right</div> 
</div>

下面重點(diǎn)針對(duì)上面HTML結(jié)構(gòu)代碼講解CSS樣式如何設(shè)置。

1.首先將container塊設(shè)置為一個(gè)Flex容器

.container{
        display: flex;
        min-height: 130px;
    }

那么container下屬的main、left和right這三個(gè)子元素自動(dòng)成為容器成員,稱為 Flex 項(xiàng)目(flex item),簡(jiǎn)稱”項(xiàng)目”。
  
2.對(duì)這三個(gè)項(xiàng)目做初始設(shè)置

.main{
    background-color: blue;
}
.left{
    background-color: green;
}
.right{
    background-color: red;
}

項(xiàng)目根據(jù)內(nèi)容進(jìn)行彈性布局:


圖片1.png

3.通過order屬性設(shè)置排列順序

可以看出三個(gè)項(xiàng)目的排序方式不一樣了,main排在了第一個(gè),要讓main在中間,left在左邊,可以通過Flex容器下的項(xiàng)目的屬性“order”屬性來設(shè)置:

.left{
    order: -1;
    background-color: green;
}

對(duì)于order屬性:定義項(xiàng)目的排列順序,越小越靠前,默認(rèn)為0。

圖片2.png

4.通過項(xiàng)目屬性flex-grow設(shè)置main的放大比例,將空余的空間用main來填充,使三個(gè)項(xiàng)目不滿一整行;默認(rèn)為0,也就是對(duì)剩余空間不做處理。

.main{
    flex-grow:1;
    background-color: blue;
}
圖片4.png

5.通過項(xiàng)目屬性flex-basis 設(shè)置left和right的固定寬度

.left{
        order: -1;
        flex-basis: 200px;
        background-color: green;
    }
    .right{
        flex-basis: 300px;
        background-color: red;
    }

這樣就實(shí)現(xiàn)了我們的目標(biāo),是不是很簡(jiǎn)單?這就是flex布局的魅力。

圖片5.png

6.最后,完整的代碼如下:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>實(shí)現(xiàn)三欄水平布局之Flex布局</title>
    <style type="text/css">
    .container{
        display: flex;
        min-height: 130px;
    }
    .main{
        flex-grow: 1;
        background-color: blue;
    }
    .left{
        order: -1;
        flex-basis: 200px;
        background-color: green;
    }
    .right{
        flex-basis: 300px;
        background-color: red;
    }
    </style>
</head>
<body>
<div class="container"> 
  <div class="main">main</div> 
  <div class="left">left</div> 
  <div class="right">right</div> 
</div>
</body>
</html>

方法四:絕對(duì)定位布局

絕對(duì)定位使元素的位置與文檔流無關(guān),因此不占據(jù)空間。這一點(diǎn)與相對(duì)定位不同,相對(duì)定位實(shí)際上被看作普通流定位模型的一部分,因?yàn)樵氐奈恢孟鄬?duì)于它在普通流中的位置。
  
  提示:因?yàn)榻^對(duì)定位的框與文檔流無關(guān),所以它們可以覆蓋頁面上的其它元素??梢酝ㄟ^設(shè)置 z-index 屬性來控制這些框的堆放次序。

言歸正傳:
  絕對(duì)定位,就相當(dāng)于萬金油一樣的存在,不論什么樣的布局,使用絕對(duì)定位都能實(shí)現(xiàn),所以對(duì)于具體的實(shí)現(xiàn)過程就不贅述,下面直接參照以下完整代碼,細(xì)細(xì)品味和驗(yàn)證即可:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>實(shí)現(xiàn)三欄水平布局之絕對(duì)定位布局</title>
    <style type="text/css">
    .container{
        position: relative;
    }
    .main,.right,.left{
        top: 0;
        height: 130px;
    }
    .main{
        margin: 0 300px 0 200px;
        background-color: blue;
    }
    .right{
        position: absolute;
        width: 300px;
        right: 0;
        background-color: red;
    }
    .left{
        position: absolute;
        width: 200px;
        background-color: green;
        left: 0;
    }
    </style>
</head>
<body>
<div class="container"> 
  <div class="main">main</div> 
  <div class="left">left</div> 
  <div class="right">right</div> 
</div>
</body>
</html>

預(yù)覽效果圖如下:


最終效果圖.png

(完)

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容