一侧收缩,一侧自动填充的双栏布局不管在面试总还是工作中都是常遇到的布局问题,甚至有面试会问三种不同的方式如何来实现。。本来想说一个双栏布局嘛,不就是float
和margin-left
可以搞定了,不过既然人家问了,我肯定还是要答的,所以刻意做了总结,边总结边发现了一个新世界,区区的双栏布局,原来也是可以有不少套路的~
利用浮动和流体布局实现双栏布局
也许看到这种实现方式-浮动和流体布局会有点陌生,不过不要着急,这应该是大多数人最常使用的双栏布局的方式,没有之一了~只是这里打算从不同的角度来进行下分析~
自适应宽度和流体布局
首先遇到自适应宽度就会想到普通块级元素自由的流特性,即普通块级元素本身的width+padding+border+margin
会自动填充父元素容器的宽度,那么既然双栏中的一栏要宽度自适应,是否可以利用普通块元素自身的流特性呢?
答案当然是可以的,不过既然是双栏布局,一栏自适应填充父元素了,那另一栏岂不是要被挤到其它行了?不要忘了,我们有浮动元素啊,浮动元素允许块级元素和自己处于同一行,所以将另一个元素设为浮动元素就可以了。
利用元素浮动实现块级元素同行排列
最先,为了实现双列布局,我们使两个兄弟块级元素中的第一个元素浮动,代码如下:
<div class="container">
<div class="float">
浮动元素
</div>
<div class="main">
自适应
</div>
</div>
//CSS
.float{
height:100px;
float:left;
background:red;
opacity:0.3;
width:200px;
}
.main{
background:green;
height:100px;
}
.container{
width:500px;
}
复制代码
如上样式设置的效果如下图1所示
可以看到,虽然看上去好像是双列布局,但是通过为左侧浮动元素的透明度可以看出,右侧元素的背景绿色也覆盖到了左侧的范围,说明,main元素并不是单纯的基于右侧的,它的起始位置还是从父元素的最左侧开始的,只是出于某种原因(和浮动元素的影响有关)它的文字内容被挤到了左侧浮动元素之外,但这并不是我们要的效果,我们需要的是单纯的左右布局的效果。
通过margin-left与浮动元素在空间上彻底隔离
那么该如何做呢?其实只要基于以上效果做一点处理就好了,我们知道普通块级元素的流特性是它的margin+border+padding+width
填充父元素怒的空间,那么这里只要把marin-left的宽度设置为左侧float元素的宽度,不就可以达到main既能自适应宽度,又会与float元素区域分离开来了吗?改良后的CSS和效果如下:
.main{
background:green;
height:100px;
margin-left:200px;//设置为何左侧浮动元素等宽
}
复制代码
利用BFC来实现双列布局
不难发现,上节的利用浮动元素和margin-left实现的双列布局有一个限制条件是,一侧必须是固定宽度的,这样右侧自适应宽度的元素才能通过设置margin-left
属性值来和左侧栏分离,那么如果不知道左侧的宽度,这时候不能单纯的依靠块级元素的流特性了,,有什么办法可以实现右侧自适应填充剩余宽度的效果吗?
答案就是BFC了,什么?BFC不就是块级格式化上下文吗,和双列布局有什么关系吗,是的。。
触发了BFC的元素能够使其子孙元素完全不影响到外界元素的的呈现,这也是为什么BFC元素不会发生margin合并,以及BFC元素有清除浮动的副作用,因为不管是产生magin合并,还是其子元素的浮动造成的父元素本身的高度塌陷均会影响到外界元素,与BFC的自身设定相违背了。。等等,不是在聊用BFC来实现双列布局吗,关margin合并,清除浮动什么事吗,不错,这里是不关margin合并的事,但是清除浮动是不是感觉很熟悉?这里要利用的正是BFC清除浮动的特性,既然我们要实现两栏布局,那么左侧浮动,右侧清除浮动,不是就可以了吗?
触发BFC的属性有很多种,这里不做过多说明了,但我们选择一种副作用相对来说比较小的属性来触发BFC,即overflow:hidden
,改良后的CSS如图所示:
.container{
width:500px;
}
.float{
height:200px;
background:red;
opacity:0.3;
float:left;
}
.main{
background:green;
height:200px;
overflow:hidden;//触发BFC
}
复制代码
可以看到,和上节的图2效果一样,实现了一个完全的双列布局,样式的核心点在于:
- 将左侧栏设为左浮动,将自身高度塌陷,使得其它块级元素可以和它占据同一行的位置。
- 右侧栏为普通块级元素,利用自身的流特性填充整行空间。
- 右侧栏设置
overflow:hidden
触发BFC特性,使得自身和左侧的浮动元素分离开来,顺着浮动元素边缘形成自己的块级上下文区域。
可以看到其实这种实现方式和上一节的实现方式很像,都利用了左侧浮动,右侧为具有流特性的普通块级元素,不同的是本节中右侧元素同时触发了BFC,使得本身自动和浮动元素分离,也就无需像上例一样手动指定margin-left
了。 有点神奇吧,已经掌握两种实现双列布局的方式了,而且实现起来比较简单,只需设置几个CSS属性就好,并且接触到了浮动,BFC两个专业术语:)。。不过,不要着急,还有终极更简单神奇的杀手锏呢~
flex实现双栏布局
flex布局总是平时听得多,但是自己用的少,所以常常忘了这种实现方式,但是还是不得不忽略的,因为flex布局实在太强大了,对于这种需求简直是小case了。。这里就单纯的贴下代码好啦
.contanier{
width:500px;
display:flex;
}
.float{
height:200px;
background:red;
opacity:0.3;
}
.main{
background:green;
height:200px;
flex-grow:1;
}
复制代码
可以看到,利用flex也可以实现在左侧宽度不确定的情况下,右侧自动填充剩余空间的双列布局,本方案的point只要记得,父元素设置为display:flex
,自动填充空间的右侧元素设置属性flex-grow:1
就可以啦,很简洁有木有,当然啦,有利有弊,弊端就是,考虑到兼容性可能就不那么友好了,毕竟flex
这么高大上的属性不是每一个浏览器都是支持的~ 关于双栏布局的三种实现方式的总结就到这里啦,不过虽然这里只提到了双栏布局,但这三种方式的每一种都是可以延伸到三栏布局的,比如第一种,通过设置左右元素的左右浮动,第二种通过嵌套多层float+BFC块元素,第三种更简单,只需加一列就好了~哈哈,废话不多说了,可以实现一下~