三欄是CSS布局中常見(jiàn)的一種布局模式册烈,顧名思義钮孵,就是將網(wǎng)頁(yè)內(nèi)容以三列的形式呈現(xiàn)骂倘。通常,三欄布局中的左欄和右欄是固定寬度的油猫,中欄隨著窗口寬度的變化而變化稠茂。本文探討欄三欄的基本實(shí)現(xiàn)思路和經(jīng)典方法柠偶,對(duì)其中涉及到的知識(shí)點(diǎn)進(jìn)行梳理情妖。
目的:實(shí)現(xiàn)一個(gè)左欄和右欄寬300px,中間欄寬度自適應(yīng)的三欄布局
基本實(shí)現(xiàn)思路
首先诱担,常規(guī)思路毡证,我們寫出3個(gè)div的HTML和CSS,分別是leftColumn(左欄)蔫仙、middleColumn(中欄)和rightColumn(右欄)料睛。
HTML:
<body>
<div id="leftDiv">左欄</div>
<div id="middleDiv">中欄</div>
<div id="rightDiv">右欄</div>
</body>
CSS:
#leftDiv {
height: 300px; /*高度設(shè)為300像素,下同*/
background-color: rgb(60,139,176); /*設(shè)置背景顏色*/
}
#middleDiv {
height: 300px;
background-color: rgb(225,236,214);
}
#rightDiv {
height: 300px;
background-color: rgb(122,122,122);
}
此時(shí)摇邦,得到的網(wǎng)頁(yè)如下圖所示:
這是因?yàn)閐iv的特性:默認(rèn)寬度最大化(頁(yè)面的100%)恤煞,默認(rèn)高度最小化(根據(jù)內(nèi)容自適應(yīng))。
上面的CSS中施籍,只指定欄高度height:300px居扒,未指定寬度,所以每個(gè)div都以寬度width:100%填滿所在行丑慎。
注意:此時(shí)若嘗試指定每個(gè)div的寬度喜喂,例如給每個(gè)div的CSS添加語(yǔ)句:
width: 100px;
得到的頁(yè)面如下圖左圖,而非右圖竿裂。
這是因?yàn)閐iv屬于塊級(jí)(block)元素玉吁,默認(rèn)情況下,塊級(jí)元素總是會(huì)另起一行腻异。
為了使塊級(jí)元素能位于同一行进副,最簡(jiǎn)單的方法是使用float屬性。我們對(duì)每個(gè)div的CSS新增語(yǔ)句:
#leftDiv,#middleDiv,#rightDiv {
float: left; /*向左浮動(dòng)*/
height: 300px;
}
使其向左浮動(dòng),得到的效果如下圖所示:
可以看到悔常,對(duì)CSS設(shè)置float:left屬性后影斑,三欄位于了同一行,寬度為其內(nèi)容的適應(yīng)寬度这嚣。此時(shí)鸥昏,我們將左欄和右欄寬度設(shè)置為300px:
#leftDiv,#rightDiv {
width: 300px; /*設(shè)置寬度為300像素*/
...
}
#middleDiv {
...
}
得到的效果如下圖所示:
此時(shí),中欄的寬度仍為其內(nèi)容的適應(yīng)寬度姐帚,我們?yōu)閙iddleDiv添加如下語(yǔ)句:
width: calc(100% - 600px); /*設(shè)置middleDiv寬度*/
calc()的作用為動(dòng)態(tài)計(jì)算長(zhǎng)度值吏垮,允許各種單位混合運(yùn)算,運(yùn)算符前后需有空格。
于是我們得到了最終效果膳汪。左欄和右欄各300px寬唯蝶,中欄根據(jù)瀏覽器窗口大小進(jìn)行動(dòng)態(tài)調(diào)整。但需要注意的是遗嗽,當(dāng)瀏覽器窗口寬度小于600px時(shí)粘我,中欄的寬度將小于0。為此痹换,我們可以為瀏覽其設(shè)置最小調(diào)整寬度征字,避免頁(yè)面混亂:
body {
min-width: 700px;
}
至此,一個(gè)三欄布局就完成了娇豫。這種實(shí)現(xiàn)思路比較符合人的思維定勢(shì)匙姜,但也存在一定的缺陷:瀏覽器加載和渲染頁(yè)面遵循從上到下的原則,這種方法中冯痢,HTML的middleDiv(中欄)位列于leftDiv(左欄)之后氮昧,所以會(huì)在leftDiv之后加載,而middleDiv往往是頁(yè)面的核心浦楣,需要優(yōu)先加載展示給用戶袖肥。
于是,我們思考將middleDiv放在HTML中的首位:
<body>
<div id="middleDiv">中欄</div>
<div id="leftDiv">左欄</div>
<div id="rightDiv">右欄</div>
</body>
CSS中振劳,我們?nèi)匀辉O(shè)置middleDiv(中欄)的寬度為100% - 600px:
#middleDiv {
width: calc(100% - 600px);
...
}
此時(shí)的界面如圖所示:
可以看到椎组,由于我們?cè)贖TML中將middleDiv(中欄)放在欄首位,所以瀏覽器窗口中澎迎,中欄顯示在最前面庐杨。這時(shí),我們需要為leftDiv(左欄)騰出空間夹供,可以使用margin-left或padding-left灵份。
margin和padding分別為盒模型的外邊距和內(nèi)邊距,此處使用兩者皆可哮洽,此處唯一的區(qū)別是padding會(huì)被底色填充而margin不會(huì)填渠。因?yàn)閎ackground-color的填充區(qū)域?yàn)閏ontent+padding+border。
還有一點(diǎn)需要注意的是鸟辅,padding值不能為負(fù)氛什,對(duì)于需要取負(fù)值時(shí),僅可使用margin匪凉。
為middleDiv(中欄)添加以下語(yǔ)句:
margin-left: 300px;
此時(shí)效果如下圖所示:
可以看到枪眉,由于增加了300px的外邊距,第一行的橫向空間被middleDiv(中欄)和leftDiv(左欄)填滿再层,rightDiv(右欄)被迫位列第二行贸铜。
此時(shí)堡纬,我們使用relative屬性對(duì)左欄和右欄進(jìn)行處理:
#leftDiv {
position: relative; /*相對(duì)定位*/
left: calc(300px - 100%); /*左移*/
...
}
#rightDiv {
position: relative;
top: -300px; /*上移*/
left: calc(100% - 300px); /*右移*/
...
}
至此,我們?cè)诒WCmiddleDiv(中欄)先行加載渲染的條件下蒿秦,完成了三欄布局烤镐。基本思路為通過(guò)相對(duì)定位實(shí)現(xiàn)棍鳖。
經(jīng)典方法
CSS三欄布局的方法有很多種炮叶,其中最經(jīng)典的方法莫過(guò)于圣杯布局和雙飛翼布局。圣杯布局因形似圣杯而得名渡处,即中欄為杯身镜悉,左右兩欄為杯耳。雙飛翼布局則是圣杯布局的一種改進(jìn)骂蓖,去掉了relative屬性积瞒,并為主體部分增加了內(nèi)容嵌套。
圣杯布局(In Search of the Holy Grail)
圣杯布局和雙飛翼布局都需要在HTML中為div增加一層“容器(container)”登下。這個(gè)容器的目的主要是為了利用padding對(duì)中欄進(jìn)行調(diào)整。
<body>
<div id="container">
<div id="middleDiv">中欄</div>
<div id="leftDiv">左欄</div>
<div id="rightDiv">右欄</div>
</div>
</body>
首先叮喳,仍然設(shè)置float:left屬性使div浮動(dòng)被芳,使其位于一行。
#leftDiv,#middleDiv,#rightDiv {
float: left;
...
}
然后馍悟,將middleDiv(中欄)的寬度width設(shè)為100%:
#middleDiv {
width: 100%;
...
}
得到如下圖所示的布局:
此時(shí)畔濒,需要將leftDiv置于第一行左側(cè):
margin-left: -100%; /* 左側(cè)邊界前移100% */
這樣處理的結(jié)果是leftDiv(左欄)被置于第一行最左端,但會(huì)覆蓋middleDiv(中欄)的部分內(nèi)容锣咒。我們需要將中欄的內(nèi)容從被覆蓋的地方拉出來(lái)侵状。一個(gè)簡(jiǎn)便的方法是對(duì)父容器container使用margin:
#container {
margin: 0 300px 0 300px;
}
此處使用padding:0 300px 0 300px; 效果相同。
此時(shí)毅整,leftDiv(左欄)也會(huì)受父容器的影響向右移動(dòng)300px趣兄,仍然覆蓋著middleDiv(中欄)的一部分,所以我們使用相對(duì)定位讓其向左移動(dòng):
#leftDiv {
position: relative;
left: -300px;
...
}
此時(shí)的布局如下圖所示:
對(duì)rightDiv(右欄)作類似處理:
#rightDiv {
margin-left: -300px; /*左側(cè)邊界前移300px*/
position: relative;
right: -300px; /*右側(cè)邊界右移300px*/
...
}
不要忘記為body設(shè)定最小寬度:
body {
min-width: 800px;
}
至此完成悼嫉。
可以看到艇潭,圣杯布局的實(shí)現(xiàn)思想是給div套上一個(gè)父容器,通過(guò)調(diào)整父容器的padding和div左右欄的相對(duì)定位來(lái)實(shí)現(xiàn)三欄布局戏蔑。
雙飛翼布局
雙飛翼布局蹋凝,源于淘寶UED,是圣杯布局的一種改進(jìn)总棵,或者說(shuō)是另一種三欄實(shí)現(xiàn)思路鳍寂。其創(chuàng)新點(diǎn)在于額外為middleDiv(中欄)增加一個(gè)子div存放其內(nèi)容。
<body>
<div id="container">
<div id="middleDiv">
<div id="content">中欄</div>
</div>
<div id="leftDiv">左欄</div>
<div id="rightDiv">右欄</div>
</div>
</body>
仍然使用float屬性來(lái)對(duì)div進(jìn)行浮動(dòng):
#leftDiv,#middleDiv,#rightDiv {
float: left;
...
}
與圣杯類似情龄,設(shè)置middleDiv(中欄)寬度為100%迄汛,且將leftDiv(左欄)拉到最左側(cè)候味,將rightDiv(右欄)作類似處理:
#middleDiv {
width: 100%;
...
}
#leftDiv {
margin-left: -100%;
}
#rightDiv {
margin-left: -300px;
}
到這一步為止,雙飛翼布局方法和圣杯CSS方法并不不同隔心。
此時(shí)白群,由于雙飛翼布局方法為middleDiv(中欄)單獨(dú)添加了一個(gè)div存放其內(nèi)容,所以對(duì)于中欄的處理硬霍,可以使用該div的margin屬性:
#content {
margin: 0 300px 0 300px;
}
此處使用padding:0 300px 0 300px; 效果相同帜慢。
同樣,不要忘記為body設(shè)定最小寬度:
body {
min-width: 800px;
}
至此完成唯卖。
可見(jiàn)粱玲,圣杯布局方法與雙飛翼布局方法的區(qū)別在于圣杯布局采用相對(duì)位置屬性(position:relative)來(lái)調(diào)整左欄和右欄位置,并使用margin/padding屬性調(diào)整中欄拜轨。而雙飛翼布局方法無(wú)需相對(duì)位置屬性抽减,而是采用為中欄內(nèi)容創(chuàng)建div的方式,通過(guò)margin/padding來(lái)實(shí)現(xiàn)布局橄碾。
總結(jié)
本文探討了三欄布局的CSS基本實(shí)現(xiàn)方法卵沉,首先以基本思路對(duì)三欄布局進(jìn)行實(shí)現(xiàn),發(fā)現(xiàn)不足法牲,進(jìn)行調(diào)整史汗。文章第二部分闡述了流行的圣杯布局方法和雙飛翼布局方法的細(xì)節(jié)和異同。除本文所述布局方法外拒垃,還存在絕對(duì)定位法停撞、table布局法、網(wǎng)格布局法悼瓮,以及十分方便的flex布局法等多種方法戈毒,各有利弊。
本文僅探討了三欄布局的基本實(shí)現(xiàn)思路與方法横堡,詳細(xì)的實(shí)現(xiàn)過(guò)程希望能夠幫助大家深入理解CSS埋市。關(guān)于其他方法的討論將在以后實(shí)際應(yīng)用時(shí)進(jìn)行總結(jié)。??