CSS布局经典问题:两栏布局-左侧固定,右侧自适应
这个问题在开发时碰过非常多次,是经典布局问题。很多公司的面试题也会问这类问题,今天就详细的来谈一下这类问题。
还有一篇类似的文章,关于三栏布局 详情请戳
题意非常明确,左侧的块宽度是固定的,右侧的宽度会随着浏览器的宽度变化的,见下图。
1.BFC
为了解决这个问题,首先,我们来理解一下何为BFC。
BFC(Block Formatting Context)直译为“块级格式化范围”。
BFC提供了一个环境,HTML元素在这个环境中按照一定规则进行布局。它不会影响到其它环境中的布局。可以把它理解成是一个独立的容器,并且这个容器的里box的布局,与这个容器外的毫不相干。
触发BFC的条件
- float的值不为none。
- overflow的值不为visible。
- display的值为table-cell, table-caption, inline-block中的任何一个。
- position的值不为relative和static。
为了加深我们理解BFC为何物,下面看一个例子,上代码。
.wrapper{ border: 5px solid #000; }
.red { background-color:red; }
.yellow { background-color:yellow; }
.orange { background-color:orange; }
.green { background-color:green; }
.box{ width:100px; height:100px; float:left; }
<div class="wrapper">
<div class="container">
<div class="red box"></div>
<div class="yellow box"></div>
</div>
<div class="container">
<div class="orange box"></div>
<div class="green box"></div>
</div>
</div>
见效果:
很明显,.wrapper中所有的box都是浮动,父级标签没有被内容撑开,虽然.red、.yellow和.orange和.green是在两个不同的div中,但是仍不会换行。这是由于设置了浮动元素的块会形成一个BFC布局,前面提到过了:
- 对于一个BFC来说它不会影响到其他环境的布局,反之亦然。
- 在BFC中,每一个元素左外边与包含块的左边相接触(对于从右到左的格式化,右外边接触右边),即使存在浮动也是如此。
- 当容器有足够的剩余空间容纳BFC的宽度时,所有浏览器都会将BFC放置在浮动元素所在行的剩余空间内。
- 在进行普通流中的块级非替换元素的高度计算时,浮动子元素不参与计算。
- 在计算生成了BFC 的元素的高度时,其浮动子元素应该参与计算。
故呈现了这样的效果。
若想要让每一个.container中的元素都单独占据一行,可以让.container变成BFC布局(overflow:hidden)。
看到这里。相信你对BFC也有一定的理解了。如若不理解,可以看看这篇文章,有可取之处。
关于Block Formatting Context--BFC和IE的hasLayout
关于IE的layout可以看看这篇文章
IE的layout属性详解
2.左侧固定,右侧自定义布局实现
回到题目,下面来看看如何实现左侧固定,右侧自适应布局
<div class="container">
<div class="left"></div>
<div class="right"></div>
</div>
2.1利用BFC之方法一
由于在BFC中,每一个元素左外边与包含块的左边相接触(对于从右到左的格式化,右外边接触右边),即使存在浮动也是如此。创建了BFC的元素不能与浮动元素重叠。且当容器有足够的剩余空间容纳BFC的宽度时,所有浏览器都会将BFC放置在浮动元素所在行的剩余空间内。利用这些特性,就可以达到效果。
.left{
float: left;
width: 200px;
height: 200px;
background: green;
}
.right{
overflow: hidden;
height: 300px;
background: red;
}
2.2利用margin-left
首先还是设置left浮动让他变为BFC,由2.1方法可知,在BFC中,每一个元素左外边与包含块的左边相接触(对于从右到左的格式化,右外边接触右边),即使存在浮动也是如此。所以left和right会重叠。然后利用margin-left让right腾出位置。
.left{
float: left;
width: 200px;
height: 200px;
background: green;
}
.right{
margin-left: 200px;
height: 300px;
background: red;
}
2.3使用绝对定位
同样,这个方法和2.2方法类似,也是left的形成BFC方式不同,就不过多描述了。
.container{
position: relative;
}
.left{
position: absolute;
left: 0;
top: 0;
width: 200px;
height: 200px;
background: green;
}
.right{
margin-left: 200px;
height: 200px;
background: red;
}
2.4利用flex布局
flex布局走天下阿。。但是兼容性问题还是摆在那里,有所取舍吧。
.container{
display: flex;
display: -webkit-box;
display: -moz-box;
display: -ms-flexbox;
width:100%;
height: 200px;
}
.left{
width: 200px;
background: green;
}
.right{
// 如果此处用width:100%会导致左侧元素不足固定宽度,因为left+right的宽度大于父级宽度,会进行一个等比缩放
//width:100%;
flex:1;
background: red;
}
2.5利用grid布局
.container{
display: grid;
grid-template-rows: 200px;
grid-template-columns: 200px auto;
width:100%;
}
.left{
background: green;
}
.right{
background: red;
}
2.6利用table-cell
.container{
display: table;
width:100%;
}
.left{
display: table-cell;
height: 200px;
width: 200px;
background: green;
}
.right{
display: table-cell;
height: 200px;
background: red;
}
知识扩展
前面提到了BFC,与之类似的还有IFC,GFC,FFC。。很晕吧,贴上两个链接,希望你看了能有所收获。
CSS魔法堂:重新认识Box Model、IFC、BFC和Collapsing margins
css3之BFC、IFC、GFC和FFC
以上内容,如有错误请指出,不甚感激。