聖盃佈局、雙飛翼佈局、Flex佈局和絕對定位佈局的幾種經典佈局的具體實現示例
題目要求:針對如下DOM結構,編寫CSS,實現三欄水平佈局,其中left、right分別位於左右兩側,left寬度為200px,right寬度為300px,main處在中間,寬度自適應。
要求:允許增加額外的DOM節點,但不能修改現有節點順序。
<div class="container">
<div class="main">main</div>
<div class="left">left</div>
<div class="right">right</div>
</div>
聖盃佈局與雙飛翼佈局針對的都是三列左右欄固定中間欄邊框自適應的網頁佈局(想象一下聖盃是主體是加上兩個耳朵;鳥兒是身體加上一對翅膀),聖盃佈局是Kevin Cornell在2006年提出的一個佈局模型概念,在國內最早是由淘寶UED的工程師(傳說是玉伯)改進並傳播開來,在中國也有叫法是雙飛翼佈局,它的佈局要求有幾點:
三列布局,中間寬度自適應,兩邊定寬;
中間欄要在瀏覽器中優先展示渲染;
允許任意列的高度最高;
可以看出我們題目的要求跟聖盃佈局和雙飛翼佈局要求一樣。
下面我們看看具體的實現方法。
方法一:聖盃佈局
1.設定基本樣式
/*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。
2.聖盃佈局是一種相對佈局,首先設定父元素container的位置:
.container {
padding: 0 300px 0 200px;
}
實現效果是左右分別空出200px和300px區域,效果如圖:
3.將主體部分的三個子元素都設定左浮動
.left, .main, .right {
min-height: 130px;
float: left;
}
出現瞭如下情況,怎麼辦,彆著急慢慢來:
4.設定main寬度為width:100%,讓其單獨佔滿一行
.main {
background-color: blue;
width: 100%;
}
5.設定left和right 負的外邊距
我們的目標是讓left、main、right依次並排,但是上圖中left和right都是位於下一行,這裡的技巧就是使用負的margin-left:
.left {
margin-left: -100%;
background-color: green;
width: 200px;
}
.right {
margin-left: -300px;
background-color: red;
width: 300px;
}
負的margin-left會讓元素沿文件流向左移動,如果負的數值比較大就會一直移動到上一行。關於負的margin的應用也是博大精深,這裡肯定是不能詳細介紹了。
設定left部分的margin-left為-100%,就會使left向左移動一整個行的寬度,由於left左邊是父元素的邊框,所以left繼續跳到上一行左移,一直移動到上一行的開頭,並覆蓋了main部分(仔細觀察下圖,你會發現main裡面的字“main”不見了,因為被left遮住了),left上移過後,right就會處於上一行的開頭位置,這時再設定right部分margin-left為負的寬度,right就會左移到上一行的末尾。
6.接下來只要把left和right分別移動到這兩個留白就可以了。可以使用相對定位移動 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;
}
至此,我們完成了三列中間自適應的佈局,也就是傳說中的聖盃佈局。完整的程式碼如下:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>實現三欄水平佈局之聖盃佈局</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浮動,但左右兩欄加上負margin讓其跟中間欄div並排,以形成三欄佈局。不同在於解決 “中間欄div內容不被遮擋”問題的思路不一樣。
他的HTML結構發生了變化:
<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>實現三欄水平佈局之雙飛翼佈局</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個div,少用大致4個css屬性(聖盃佈局container的 padding-left和padding-right這2個屬性,加上左右兩個div用相對佈局position: relative及對應的right和left共4個屬性,;而雙飛翼佈局子div裡用margin-left和margin-right共2個屬性,比聖盃佈局思路更直接和簡潔一點。簡單說起來就是:雙飛翼佈局比聖盃佈局多建立了一個div,但不用相對佈局了。
想知道更多關於聖盃佈局和雙飛翼佈局,請參考:
方法三:Flex佈局
Flex 是 Flexible Box 的縮寫,意為”彈性佈局”,用來為盒狀模型提供最大的靈活性。
任何一個容器都可以指定為 Flex 佈局,所以Flex 佈局將成為未來佈局的首選方案。
對於Flex佈局的一些具體語法實現,可參見阮一峰大神的Flex 佈局教程:語法篇;網友 JailBreak 為Flex佈局製作了 Demo,可以參考。
想了解Flex佈局的具體例項可參見阮一峰大神的Flex 佈局教程:例項篇;想直接檢視Flex佈局例項,你可以到直接到codepen檢視Demo。
接下來講一下此例項的具體實現:
1.首先將container塊設定為一個Flex容器
.container{
display: flex;
min-height: 130px;
}
那麼container下屬的main、left和right這三個子元素自動成為容器成員,稱為 Flex 專案(flex item),簡稱”專案”。
2.對這三個專案做初始設定
.main{
background-color: blue;
}
.left{
background-color: green;
}
.right{
background-color: red;
}
專案根據內容進行彈性佈局:
3.通過order屬性設定排列順序
可以看出三個專案的排序方式不一樣了,main排在了第一個,要讓main在中間,left在左邊,可以通過Flex容器下的專案的屬性“order”屬性來設定:
.left{
order: -1;
background-color: green;
}
對於order屬性:定義專案的排列順序,越小越靠前,預設為0。
4.通過專案屬性flex-grow設定main的放大比例,將空餘的空間用main來填充,使三個專案不滿一整行;預設為0,也就是對剩餘空間不做處理。
.main{
flex-grow:1;
background-color: blue;
}
5.通過專案屬性flex-basis 設定left和right的固定寬度
.left{
order: -1;
flex-basis: 200px;
background-color: green;
}
.right{
flex-basis: 300px;
background-color: red;
}
這樣就實現了我們的目標,是不是很簡單?這就是flex佈局的魅力。。。
6.最後,完整的程式碼如下:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>實現三欄水平佈局之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>
方法四:絕對定位佈局
絕對定位使元素的位置與文件流無關,因此不佔據空間。這一點與相對定位不同,相對定位實際上被看作普通流定位模型的一部分,因為元素的位置相對於它在普通流中的位置。
提示:因為絕對定位的框與文件流無關,所以它們可以覆蓋頁面上的其它元素。可以通過設定 z-index 屬性來控制這些框的堆放次序。
言歸正傳:
絕對定位,就相當於萬金油一樣的存在,不論什麼樣的佈局,使用絕對定位都能實現,所以對於具體的實現過程就不贅述,下面直接上程式碼,不懂的call我:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>實現三欄水平佈局之絕對定位佈局</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>
實現結果當然是一樣的啦!
(完)