前言
所谓三栏布局,即使指两边定宽,中间宽度自使用的布局方式,在过去,一直是一个麻烦的问题,
为了解决这个问题,有各种奇技淫巧,最出名的非圣杯布局和双飞翼布局莫属了,但是自CSS3发展以来,
特别是flexbox布局的支持度越来越好,这个问题也越来越淡化了
正文
浮动布局
HTML如下:
<div class="left">Left</div> <div class="right">Right</div> <div class="main">Main</div>
CSS如下:
body, html { height: 100%; padding: 0; margin: 0; } .left{ background: red; width:100px; float: left; height:100%; } .main{ background:blue; height:100%; margin-left:100px; margin-right:200px; } .right{ background:red; width:200px; float: right; height:100%; }
浮动布局代码比较简洁,同时也易于理解,但是浮动往往会带来塌陷等问题,而且浮动渲染计算量
较大,在移动端性能表现较差。另一个需要注意的是,main即中间部分需要放在最后,如果是left-main-right的方式
纳闷main部分将会占满剩余空间,right也就被挤到下一行了,相反,如果我们设置了right和left,在设置main
main部分将会流入left和right的下面,从而达到我们的目的
绝对定位
HTML如下:
<div class="left">left</div> <div class="main">main</div> <div class="right">right</div>
CSS如下:
body, html { height: 100%; padding: 0; margin: 0; } .left, .right { position: absolute; top: 0; background: red; height: 100%; } .left { left: 0; width: 100px; } .right { right: 0; width: 200px; } .main { margin-left: 100px; margin-right: 200px; height: 100%; background: blue; }
该方法有个明显的缺点,就是如果中间栏含有最小宽度限制,或是含有宽度的内部元素,当浏览器宽度小到一定程度,会发生层重叠的情况
圣杯布局
圣杯布局巧妙的利用负margin来使元素上移,再结合相对定位,移到外层容器的padding位置,从而达到目标 HTML如下:
<div class="main">main</div> <div class="left">left</div> <div class="right">right</div>
CSS如下:
body, html { height: 100%; padding: 0; margin: 0; } body{ padding-left:100px; padding-right:200px; } .left{ background: red; width:100px; float: left; margin-left:-100%;/*-100%:1、导致left超出body内容(此时body内容宽度只有100%-200-100)移到上层2:margin是根据父元素的宽度的,所以-100%就到上层body内容的最前*/ position: relative; left:-100px;/*-100px为了超出body内容左边,到达视窗最左*/ height:100%; } .main{ background: blue; width:100%; height:100%; float: left; } .right{ background:red; width:200px; height:100%; float: left; margin-left:-200px;/*-200px为了超出body内容到达上一层body内容最后*/ position: relative; right:-200px;/*-200px是为了向右偏移回到视窗最右*/ } .container{ width:500px; height:200px; }
问题:如果外层内容盒宽度过小,不足以容纳.left的宽度,那么.left依然会被保留在下层
双飞翼布局
双飞翼布局与圣杯布局原理类似,只不过是取消了外层的padding,从而使内容盒等于padding-box从而避免了.left上移后需要设置left值移动到padding HTML如下:
<div class="main"> <div class="inner"> main </div> </div> <div class="left"> left </div> <div class="right"> right </div>
CSS如下:
body, html { height: 100%; padding: 0; margin: 0; } body{ /*padding-left:100px;*/ /*padding-right:200px;*/ } .left{ background: red; width:100px; float: left; margin-left:-100%;/*-100% 1:是为了超出body内容(此时body内容为100%)最左 2:到达body上层内容最左也就是视窗最左 /*position: relative;*/ /*left:-100px;*/ height:100%; } .main{ background: blue; width:100%; height:100%; float: left; } .right{ background:red; width:200px; height:100%; float: left; margin-left:-200px;/*-200px 1:是为了超出body内容(此时body内容为100%)最左 2:到达body上层内容最右也就是视窗最右 /*position: relative;*/ /*right:-200px;*/ } .inner{ margin-left:100px; margin-right:200px; }
与圣杯布局不同的地方已用注释指出,而双飞翼问题与圣杯一样
flexbox布局
flexbox布局可谓是最为理想的解决方案了,一方面,代码简洁易懂,另一方面,当宽度太小时,也可以通过伸缩,避免重叠 HTML如下:
<div class="main">main</div> <div class="left">left</div> <div class="right">right</div>
CSS如下:
body,html{
height:100%;
padding: 0;
margin:0;
}
body{
display: flex;
flex-flow:row nowrap;
}
.left{
background: red;
width:100px;
height:100%;
order:0;
}
.main{
background-color: blue;
flex:1;
height:100%;
order:1;
}
.right{
background: red;
width:200px;
height:100%;
order:2;
}