天天看點

CSS三列布局之聖杯布局、雙飛翼布局

開門見山,實作如下效果:

CSS三列布局之聖杯布局、雙飛翼布局

技術點:

​ 浮動:搭建完整的布局架構

​ margin為負值調整旁邊兩列的位置 使三列布局到一行上

​ 使用相對定位:調整調整旁邊兩列的位置 使旁邊兩列調整到兩頭

先回退到結構:

CSS三列布局之聖杯布局、雙飛翼布局

html:

<body>
    <div id="header">header</div>
    <div id="content" class="clearfix">
        <div class="middle">middle</div>
        <div class="left">left</div>
        <div class="right">right</div>
    </div>
    <div id="footer">footer</div>
</body>
           

css:

* {
    margin: 0;
    padding: 0;
}

#header, #footer {
    height: 20px;
    text-align: center;
    border: 1px solid deeppink;
    background-color: gray;
}
           

接下來處理我們最重要的content部分

  • 把主列放在文檔流最前面,使主列優先加載。(即我們的middle div)
  • 使用浮動,content使用clearfix清除浮動,加上背景色區分
#content .middle, #content .left, #content .right {
    float: left;
}
.clearfix {
    *zoom: 1;
}
.clearfix:after{
    content: "";
    display: block;
    clear: both;
} 
           
CSS三列布局之聖杯布局、雙飛翼布局

這時middle left right三個div已經同在一行,接着

  • 定主列middle寬度為100%
  • 左右定200px
#content .middle {
    background-color: #FFFF00;
    width: 100%;
}
#content .left, #content .right {
    background-color: pink;
    width: 200px;
}
           

得到:

CSS三列布局之聖杯布局、雙飛翼布局

現在我們需要left和right和主列同行,而且left在左、right在右。可以采用margin為負值調整旁邊兩列的位置

  • left使用margin-left把它的邊界往左邊退對應父級的100%
  • right使用margin-left把它的邊界往左邊退一個它自身的寬度
#content .left {
    margin-left: -100%;
}
#content .right {
    margin-left: -200px;
}
           
CSS三列布局之聖杯布局、雙飛翼布局

得到如此狀态後,剩下middle 主列内容的顯示,聖杯布局和雙飛翼布局采用了兩種不同的做法處理。下面進入正題:

聖杯布局

  • 對content盒子使用padding,上下不動,左右一個盒子寬度(即200px)
  • (為什麼不對middle使用padding?答:為了撐開元素,middle已經給定了100%的寬度,是以使用padding隻會向外擴大盒子。這裡給雙飛翼布局做個鋪墊)
CSS三列布局之聖杯布局、雙飛翼布局

前端的xy軸,正值向内縮,負值向外擴:

CSS三列布局之聖杯布局、雙飛翼布局

是以

  • 使用相對定位使旁邊兩列調整到兩頭
#content .left {
    margin-left: -100%;
    position: relative;
    left: -200px;
}
#content .right {
    margin-left: -200px;
    position: relative;
    right: -200px;
}
           
CSS三列布局之聖杯布局、雙飛翼布局

進而完成了我們的三列布局。

雙飛翼布局

  • 上面說到padding的問題
  • 在middle盒子中内嵌一個盒子,利用内嵌盒子繼承了父元素寬度使用padding使得盒子縮短。
<body>
    <div id="header">header</div>
    <div id="content" class="clearfix">
        <div class="middle">
            <div class="m_inner">
                middle
            </div>
        </div>
        <div class="left">left</div>
        <div class="right">right</div>
    </div>
    <div id="footer">footer</div>
</body>
           
#content .middle .m_inner {
    padding: 0 200px;
}
           
CSS三列布局之聖杯布局、雙飛翼布局

進而完成我們的三列布局。

兩組實作的對比:

  1. 兩種布局方式都是把主列放在文檔流最前面,使主列優先加載。
  2. 兩種布局方式在實作上也有相同之處,都是讓三列浮動,然後通過負外邊距形成三列布局。
  3. 兩種布局方式的不同之 處在于如何進行中間主列位置:
    • 聖杯布局是利用父容器的左右内邊距+兩個從列相對定位;
    • 雙飛翼布局是把主列嵌套在一個新的父級塊中 利用主列的左右外邊距進行布局調整

下面還有一點

僞等高問題

如下面這種情況:

CSS三列布局之聖杯布局、雙飛翼布局

僞等高解決方法:

利用padding-bottom把盒子撐開,再利用margin-bottom把邊距收回來。

#content .middle, #content .left, #content .right {
    padding-bottom: 10000px;
    margin-bottom: -10000px;
}
           
CSS三列布局之聖杯布局、雙飛翼布局

此時content盒子的下邊框是在原來正常位置的,我們再把溢出的内容隐藏就可以啦。

#content {
    overflow: hidden;
}
           
CSS三列布局之聖杯布局、雙飛翼布局

雙飛翼布局完整代碼(聖杯就讓大家先開始動動手啦):

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<style type="text/css">
			* {
				margin: 0;
				padding: 0;
			}
			body{
				min-width: 600px;
			}
			/* 頭部腳步 */
			#header, #footer {
				border: 1px solid;
				background-color: gray;
				text-align: center;
			}
			
			/* 三列僞等高 */
			#content .middle, #content .left, #content .right {
				padding-bottom: 10000px;
				margin-bottom: -10000px;
				height: 50px;
				line-height: 50px;
				float: left;
			}
			#content {
				overflow: hidden;
			}
			
			/* 雙飛翼 */
			#content .middle {
				background-color: deeppink;
				width: 100%;
			}
			#content .middle .m_inner {
				padding: 0 200px;
			}
			
			#content .left, #content .right {
				background-color: pink;
				width: 200px;
				text-align: center;
			}
			#content .left {
				margin-left: -100%;
			}
			#content .right {
				margin-left: -200px;
			}
			
			
		</style>
	</head>
	<body>
		<div id="header"><h4>header</h4></div>
		<div id="content">
			<div class="middle">
				<div class="m_inner">
					middle
				</div>
			</div>
			<div class="left">left</div>
			<div class="right">right</div>
		</div>
		<div id="footer"><h4>footer</h4></div>
	</body>
</html>