圣杯布局和双飞翼布局
是什么
圣杯布局和双飞翼布是左右两栏固定宽度,中间部分自适应的三栏布局,并且要求中间栏要优先渲染。
圣杯布局是歪果仁提出的,双飞翼布局是圣杯布局的优化版,由淘宝UED提出。它们的效果图类似,但是在解决”中间栏div内容不被遮挡“问题上的实现方法不同。效果图:
圣杯布局
代码:
<!--html-->
<div class="container">
<div class="middle"></div>
<div class="left"></div>
<div class="right"></div>
</div>
<!--css-->
.container {
padding: 0 220px 0 200px;
overflow: hidden;
}
.left,.middle,.right {
position: relative;
float: left;
height:200px;
}
.left {
margin-left: -100%;
left: -200px;
width: 200px;
background-color: red;
}
.right {
margin-left: -220px;
right: -220px;
width: 220px;
background-color: blue;
}
.middle {
width: 100%;
min-width: 200px;
background-color: yellow;
}
思路:
首先将middle块放在前面,给middle设置width:100%(自适应),left、right设置上各自的宽度。在他们的父元素块设置内边距。接着给left、middle、right三个设置相对位置和浮动float: left,使它们脱离文档流,这时候它们呈现的是:middle独占一行(因为width:100%),left、right挨在一起在第二行,left左边与middle左边对齐。再给left、right设置他们的负外边距和相对位移,使它们位于左右两侧。
注意:
- middle要放在left、right前面,这样才能优先渲染;
- 给container设置overflow: hidden; 形成BFC撑开文档,防止高度坍塌;
- 要给它们的父元素container设置内边距,以预留出左右块的位置。我试了一下用外边距,也是可以的,但此时在清除浮动的时候就不要用给父元素设置overflow:hidden这个方法了,因为裁剪边界是border,此时左右块算是“溢出内容”;
- 理解负边距的作用:根据浮动的特性
浮动框的上边缘会去贴当前行盒的上边缘或是之前浮动框的下边缘,左浮动框的左边缘会去贴包含框的左边缘,或者他之前的左浮动框的右边缘。如果当前行剩余的空间容不下一个浮动框,它就会换行。
因此我们看到left在第二行是因为Middle的自适应占满了一行,放不下它了。通过设置left的margin-left:-100%可以使它上移一行,同时right向左移占据left原先位置,同理,right的margin-left:-100px使它上移并靠右;
- 通过设置负外边距,left、right确实上移至第一行,但它们覆盖在middle上,会遮挡middle的内容。那给container设置padding不就好了吗?实践证明这样做只会在左右两边留出空白,而left还是会和middle黏在一起,因为它们都是该父元素的内容。因此这里通过给left、right设置相对位置来移动它们的位置;
双飞翼布局
代码
<!--html-->
<div class="container">
<div class="middle">
<div class="inner"></div>
</div>
<div class="left"></div>
<div class="right"></div>
</div>
<!--css-->
.container {
overflow: hidden;
}
.left,.middle,.right {
float: left;
min-height: 130px;
}
.left {
margin-left: -100%;
width: 200px;
background-color: red;
}
.right {
margin-left: -220px;
width: 220px;
background-color: blue;
}
.middle {
width: 100%;
height: 100%;
background-color: yellow;
}
.inner {
margin: 0 220px 0 200px;
min-height: 130px;
background: yellow;
word-break: break-all;
与圣杯布局不同的是:在middle块增加了一个子块inner,同样给left、middle、right设置浮动:float:left,但这里不给它们设置相对定位,也不给父元素container设置padding,而是通过设置子元素inner的margin来预留位置,同样设置left、right的margin-left(或padding)将其移动到左右两侧。
双飞翼布局会一直随着浏览器可视区域宽度减小从而不断挤压中间部分宽度。在单独部分内容扩充的时候,底部会参差不齐。解决方法(学习自掘金):
给left、middle、right设置上 padding-bottom: 9999px; margin-bottom: -9999px;
可以把两个值反过来吗? 答案是不可以。padding负值不起效果,相当于把padding取消掉。可以实践试一试。
最小页面宽度
自适应会随着网页的大小改变宽度,想要页面正常显示,就需要设置一个最小页面宽度。由于圣杯布局中left使用了position: relative,也就是说在center开始的区域,还存在着一个left的宽度。因此:
圣杯布局 min-width = LeftWidth * 2 + RightWidth;
双飞翼布局 min-width = LeftWidth + RightWidth;