文章目录
三栏式布局
三栏布局,两边的盒子宽度固定,中间盒子自适应,“圣杯”和“双飞翼就是三栏式布局,它们实现的效果是一样的,差别在于其实现的思想。
圣杯布局
方法1:使用float布局框架 , 用margin为负值 , position: relative定位
圣杯:父盒子包含三个子盒子(左,中,右)
- 中间盒子的宽度设置为 width: 100%; 独占一行;
- 使用负边距(均是 margin-left)把左右两边的盒子都拉上去和中间盒子同一行;
- .left {margin-left:-100%;} 把左边的盒子拉上去
- .right {margin-left:-右边盒子宽度px;} 把右边的盒子拉上去
- 父盒子设置左右的 padding 来为左右盒子留位置;
- 对左右盒子使用相对布局来占据 padding 的空白,避免中间盒子的内容被左右盒子覆盖;
一起来看看淘宝的头部实现:
通过缩放页面就可以发现,随着页面的宽度的变化,这三栏布局是中间盒子优先渲染,两边的盒子框子固定不变,即使页面宽度变小,也不影响我们的浏览
分析:
基础布局
<div class="header">头部</div>
<div class="container">
<div class="center">中</div>
<div class="left">左</div>
<div class="right">右</div>
</div>
<div class="footer">底部</div>
.header{
width: 100%;
height: 100px;
background-color: rgb(228, 127, 127);
}
.footer{
width: 100%;
height: 100px;
background-color: rgb(189, 85, 85);
}
.container{
width: 100%;
}
.center{
width:100%;
height: 100px;
background-color: rgb(129, 113, 221);
}
.left{
width: 200px;
height: 100px;
background-color: rgb(175, 226, 133);
}
.right{
width: 100px;
height: 100px;
background-color: rgb(133, 226, 221);
}
浮动
出现了高度塌陷,底部footer补位上来了
给footer清除浮动带来的影响
[css] 解决问题—高度塌陷
大家可以看到,三栏并没有在父元素的一行显示,就是因为中间盒子我们给了百分之百的宽度。所有左右两个盒子才会被挤下来。
那么如何让它们呈现出一行三列的效果呢?那就要让左边的盒子要到中间盒子的最左边,右边的盒子到中间盒子的最右边。换个想法,如果中间盒子不是100%的宽度,那么按照文档流,左边的盒子一定会在中间盒子的后面显示,接着显示右边的盒子。但是现在中间盒子是满屏了的,所以左右两个盒子被挤到下一行显示。我们要做到的是让左右两个盒子都上去。此时,CSS的负边距(negative margin)该上阵了。
也可以这样理解:margin负值会改变元素占据的空间,你要是不给他负值,一定是在第二行显示,因为他占据空间,第一行没有地方放他,你要是给一个-100px,和他宽度一样,那他占据的空间就是0,自然就回跑到上面去,
利用margin-left的负值将左侧栏挪上来
左侧栏margin-left赋值为-100%
左侧上去后,右侧就往前走一走
让右侧上来,
利用margin-left的负值将右侧栏挪上来
右侧栏margin-left赋值为负的自身宽度。
注意:这里的左右侧栏都是附在内容栏上的,内容栏被压在下面。(把中间部分height扩大,这样看的清晰)
将内容栏被左右压在底下的部分,通过container添加padding属性透出来。
左右侧边栏利用position: relative,移出内容区域
把中间的紫色高度恢复为100px
代码:
- 先写center部分,width 100%
- center,left,right都是左浮动
- 设置margin-left为负值让left和right部分回到与center部分同一行
- 父容器container设置padding-left和padding-right
- 设置相对定位,让left和right部分移动到两边
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.header{
width: 100%;
height: 100px;
background-color: rgb(228, 127, 127);
}
.footer{
width: 100%;
height: 100px;
background-color: rgb(189, 85, 85);
clear: both;
}
.container{
width: 100%;
padding: 0 100px 0 200px;
box-sizing: border-box;
}
.center{
width:100%;
height:100px;
background-color: rgb(129, 113, 221);
float: left;
}
.left{
width: 200px;
height: 100px;
background-color: rgb(175, 226, 133);
float: left;
margin-left: -100%;
position: relative;
left: -200px;
}
.right{
width: 100px;
height: 100px;
background-color: rgb(133, 226, 221);
float: left;
margin-left: -100px;
position: relative;
left: 100px;
}
</style>
</head>
<body>
<div class="header">头部</div>
<div class="container">
<div class="center">中</div>
<div class="left">左</div>
<div class="right">右</div>
</div>
<div class="footer">底部</div>
</body>
</html>
缺点
center部分的最小宽度不能小于left部分的宽度
其中一列内容高度拉长,其他两列的高度不会自动填充
方法2:calc
兼容到IE9
html,body {
height: 100%;
overflow: hidden;
}
.container {
height: 100%;
}
.left,.right {
width: 200px;
min-height: 200px;
background: lightblue;
float: left;
}
.center {
width: calc(100% - 400px);
min-height: 200px;
background: lightsalmon;
float: left;
}
方法3: flex布局
html,body {
height: 100%;
overflow: hidden;
}
.container{
display: flex;
/*space-between:空白均匀分布到元素间*/
justify-content: space-between;
height: 100%;
}
.left,.right{
/*flex:放大倍数 缩小倍数 占据大小*/
flex: 0 0 200px;
height: 200px;
background: lightblue;
}
.center{
/*flex:1 把剩余空间全都占据(自动分配占据空间)*/
flex: 1;
min-height: 200px;
background: lightsalmon;
}
<div class="container">
<div class="left"></div>
<div class="center"></div>
<div class="right"></div>
</div>
方法4 定位方式布局
html, body {
height: 100%;
overflow: hidden;
}
.container{
position: relative;
height: 100%;
}
.left,.right{
position: absolute;
top: 0;
width: 200px;
min-height: 200px;
background: lightblue;
}
.left{
left: 0;
}
.right{
right: 0;
}
.center{
margin: 0 200px;
min-height: 200px;
background: lightsalmon;
}
<div class="container">
<div class="left"></div>
<div class="center"></div>
<div class="right"></div>
</div>
双飞翼布局
双飞翼:父盒子包含三个子盒子(左,中,右),中间的子盒子里再加一个子盒子。
- 中间盒子的宽度设置为 width: 100%; 独占一行;
- 使用负边距(均是 margin-left)把左右两边的盒子都拉上去和中间盒子同一行;
- 在中间盒子里面再添加一个 div,然后对这个 div 设置 margin-left 和 margin-right来为左右盒子留位置;
分析:
<div class="header">头部</div>
<div class="container">
<!-- 中间的 div 必须写在最前面 -->
<div class="main">
<div class="center">中间弹性区</div>
</div>
<div class="left">左边栏</div>
<div class="right">右边栏</div>
</div>
<div class="footer">底部</div>
从上面的DOM结构来看,双飞翼布局与圣杯布局最大的不同点便是在此,双飞翼布局中,将中间栏放在一个div内部包裹起来了,多了一层DOM结构
基础布局
为左右两列预留出空间,设置center的左右margin。
将左边栏放置到预留位置:
将右边栏放置到预留位置:
代码
- 先写center部分,width 100%
- center,left,right都是左浮动
- 在中间盒子里再增加一个子盒子,设置子盒子的 margin-left, margin-right来让出空位,
- 设置margin-left为负值让left和right部分回到与center部分同一行
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.header {
width: 100%;
height: 100px;
background-color: rgb(228, 127, 127);
}
.footer {
width: 100%;
height: 100px;
background-color: rgb(189, 85, 85);
clear: both;
}
.container {
width: 100%;
height: 100px;
}
.main {
width: 100%;
height: 100px;
background-color: rgb(129, 113, 221);
float: left;
}
.main .center{
height: 100px;
background-color: rgb(233, 162, 215);
margin-left: 200px;
margin-right: 100px;
}
.left {
width: 200px;
height: 100px;
background-color: rgb(175, 226, 133);
float: left;
margin-left: -100%;
}
.right {
width: 100px;
height: 100px;
background-color: rgb(133, 226, 221);
float: left;
margin-left: -100px;
}
</style>
</head>
<body>
<div class="header">头部</div>
<div class="container">
<!-- 中间的 div 必须写在最前面 -->
<div class="main">
<div class="center">中间弹性区</div>
</div>
<div class="left">左边栏</div>
<div class="right">右边栏</div>
</div>
<div class="footer">底部</div>
</body>
</html>
圣杯和双飞翼异同
圣杯布局和双飞翼布局解决的问题是一样的,都是两边定宽,中间自适应的三栏布局,中间栏要在放在文档流前面以优先渲染。
- 两种方法基本思路都相同:首先让中间盒子 100% 宽度占满同一高度的空间,在左右两个盒子被挤出中间盒子所在区域时,使用 margin-left 的负值将左右两个盒子拉回与中间盒子同一高度的空间。接下来进行一些调整避免中间盒子的内容被左右盒子遮挡。
- 主要区别在于 如何使中间盒子的内容不被左右盒子遮挡:
- 圣杯布局的方法:设置父盒子的 padding 值为左右盒子留出空位,再利用相对定位对左右盒子调整位置占据 padding 出来的空位;
- 双飞翼布局的方法:在中间盒子里再增加一个子盒子,直接设置这个子盒子的 margin 值来让出空位,而不用再调整左右盒子。
简单说起来就是双飞翼布局比圣杯布局多创建了一个 div,但不用相对布局了,少设置几个属性。
这样说也行
说说圣杯布局与双飞翼布局的区别吧:
相同点:
1.两个都是三栏式布局,中间栏优先放,保证优先渲染
2.实现方式都是左浮动
不同点:
1圣杯布局是中间栏为两边腾开位置。双飞翼布局则是中间栏不变,将内容部分为两边腾开位置
参考:
CSS 布局经典问题初步整理