浮動布局並不是再是流行的布局方式,不過基於浮動的經典布局還是經常出現在前端面試中,聖杯布局和雙飛翼布局就是其中常考核的知識點。聖杯布局和雙飛翼布局都是前端中三列設計布局方式,要求主要中間內容優先渲染,左右內容寬度固定,中間主要內容寬度自適應排布。聖杯布局和雙飛翼布局都沒有使用絕對定位,而是應用浮動、負外邊距以及相對定位這幾個核心知識點來實現。

聖杯布局
聖杯布局是讓左右固定欄和中間自適應的主內容欄處於同一容器包裹中,容器(#container)設置padding-left、padding-right值,其中padding-left值與左側欄(#left)的寬度值相等,padding-right值與右側欄(#right)的寬度值相等,中間自適應欄的寬度設置為100%,讓中間自適應欄的寬度與容器的內容盒寬度相等。通過定位設置讓左側欄(#left)在中間欄(# center)左側恰好容納容器padding-left的空間,右側欄(# right)在中間欄(# center)右側恰好容納容器padding-right的空間。
聖杯布局的主要框架草圖如下所示:

聖杯布局的HTML架構代碼:
<div id='header'>#header</div>
<div id='container'>
<div id='center'>#center</div>
<div id='left'>#left</div>
<div id='right'>#right</div>
</div>
<div id='footer'>#footer</div>
聖杯布局的CSS代碼:
* {
border-width: 0;
}
body {
min-width: 350px;
}
#header,
#footer {
height: 100px;
background: #ccc;
}
#container {
padding-left: 200px;
padding-right: 150px;
box-sizing:border-box;
min-width:550px;
}
#center {
float: left;
width: 100%;
background: #f96d9f;
}
#left {
width: 200px;
float: left;
margin-left: -100%;
position: relative;
left: -200px;
background: aqua;
}
#right {
width: 150px;
float: left;
margin-right: -150px;
background: yellowgreen;
}
#left,
#right,
#center {
min-height: 100px;
}
/* 外圍樣式 */
#header,
#footer,
#center,
#left,
#right {
display: flex;
justify-content: center;
align-items: center;
font-family: 'Source Code Pro';
font-size: 20px;
}
#footer {
clear: both;
}
外圍樣式是為了文字美化居中而設置的代碼,並非聖杯布局CSS代碼主體部分。聖杯布局的代碼的核心難點是如何不通過絕對定位來讓文檔流中后面的元素位於前面元素,這里運用了浮動、負外邊距以及相對定位來實現。
這是左側欄的核心代碼:
#left {
width: 200px;
float: left;
margin-left: -100%;
position: relative;
left: -200px;
}
這里margin-left: -100%;由於負外邊距-100%計算值是宿主元素內容盒模型的寬度,其寬度大於左側欄寬度200px。所以浮動的左側欄通過負外邊距上浮到上層,以中間欄(#center)的右側外邊緣為基准線,向左側移動相當於宿主元素內容盒模型寬度的距離,恰好位於中間欄(#center)的左側,占據容器(#container)padding-left的位置。
#right {
width: 150px;
float: left;
margin-right: -150px;
}
當左側欄(#left)由於負外邊距上移后,右側欄(#right)由於左浮動位於容器(#container)的內側左邊緣。同樣負外邊距 margin-right: -150px; 設置令右側欄(#right)上移,同樣是以中間欄(#center)的右側外邊緣為基准線作為右側欄(#right)的最左側邊接觸。
這樣通過對浮動元素左、右負邊距的設置,令原本位於中間欄(#center)下方的浮動元素左側欄(#left)、右側欄(#right)上移是聖杯布局的理解難點。
聖杯布局的最小尺寸問題
聖杯布局是基於左側欄(#left)負外邊距 margin-left: -100%;設置來實現的,但是左側欄上移有個前提條件,就是margin-left的負值與左側欄(#left)自身的內容寬度相加后的值不大於上一行剩余空間,才可以實現左側欄(#left)上移。這里中間欄(#center)完全占據上一行剩余空間,margin-left的負值與左側欄(#left)自身的內容寬度相加后的值不大於0才可以上移,否則左側欄(#left)仍然停留在第二行,就無法實現聖杯布局目的。所以中間欄(#center)的寬度需要不小於左側欄(#left)寬度,才能滿足聖杯布局的實現。
聖杯布局的最小尺寸計算:若左側欄(#left)的寬度為X,右側欄的寬度為Y,那么容器(#container)最小尺寸計算:2X+Y。
在上述實例中,聖杯布局最小尺寸為2x200+150=550px。所以容器(#container)需要設置最小尺寸min-width:550px;,同時這里550px是容器邊框盒的尺寸,為了避免采用默認內容盒尺寸進行轉換計算,就采用設置:box-sizing:border-box;。
#container {
padding-left: 200px;
padding-right: 150px;
box-sizing:border-box;
min-width:550px;
}
雙飛翼布局
雙飛翼布局同樣未采用絕對定位,它是在聖杯布局的基礎上進行改進的布局形式。雙飛翼布局布局中左側欄(#left)、右側欄(#right)、中間欄(#center)都是兄弟元素。通過中間欄(#center)的內部元素(# inner)設置左右外邊距為左側欄(#left)、右側欄(#right)預留位置空間,其余通過負邊距設置令浮動元素上移的設置原理相同。
雙飛翼布局的結構示意圖:

雙飛翼布局HTML代碼:
<div id='header'>#header</div>
<div id='center'>
<div id='inner'>center</div>
</div>
<div id='left'>#left</div>
<div id='right'>#right</div>
<div id='footer'>#footer</div>
雙飛翼布局CSS代碼:
* {
border-width: 0;
}
body {
min-width: 350px;
}
#header,
#footer {
height: 100px;
background: #ccc;
}
#container {
padding-left: 200px;
padding-right: 150px;
box-sizing: border-box;
min-width: 550px;
}
#center {
float: left;
width: 100%;
background: #f96d9f;
}
#inner{
margin-left:200px;
margin-right:150px;
}
#left {
width: 200px;
float: left;
margin-left: -100%;
background: aqua;
}
#right {
width: 150px;
float: left;
margin-left: -150px;
background: yellowgreen;
}
#left,
#right,
#center {
min-height: 100px;
}
/* 外圍樣式 */
#header,
#footer,
#center,
#inner,
#left,
#right {
display: flex;
justify-content: center;
align-items: center;
font-family: 'Source Code Pro';
font-size: 20px;
}
#footer {
clear: both;
}
雙飛翼布局與聖杯布局相比,沒有最小值限制,比其布局適應寬度范圍更廣泛。
