本文讨论的是两列自适应布局:左列定宽/不定宽,右列自适应。
虽然分这两种情况,但实际上不定宽的方案同样适用于定宽的场景,因此不定宽的方案泛用度更高。
<div class="parent"> <div class="left"><p>left</p></div> <div class="right-fix"> <div class="right"> <p>right</p><p>right</p> </div> </div> </div>
.left{ float: left; //向左浮动 width: 100px; //固定宽度 position: relative;//由于.left与.right-fix重合,且.right-fix在DOM树上的位置比.left要后,因此.right-fix会遮挡住.left,设置.left为relative可以让其冒出来。 } .right-fix{ float: right; //向右浮动 width: 100%; //为了自适应设为100% margin-left: -100px;//由于宽度设为100%,.right-fix遭到浏览器换行处理;因此通过设置负的margin值,在左侧制造出100px的空白,使.right-fix与.left重合(即处于同一行) } .right{ margin-left: 120px; //由于.left和.right-fix重合了,因此给.right设置一个margin-left,避免内容区(.right)与.left重合。另外,120px - 100px = 多出来的20px实际上就相当于.left和.right之间的间隔了。 }
这个方法其实已经是兼顾到低版本IE的完善版本了,缺点是代码冗长,而且有两个关键知识点比较难理解:
给.left加上position:relative;怎么就能让.left冒出来而不受.right-fix的遮挡了呢?
.right-fix设置负的margin-left,怎么就能使.left与.right-fix重合了呢?
再者,这个方案由于.right-fix的margin-left和.left的width高度耦合,因此无法实现自适应,只能应用在左列(当然右列也成)固定宽度的场景。
BFC
<div class="parent"> <div class="left"> <p>left</p> </div> <div class="right"> <p>right</p> <p>right</p> </div> </div>
.left{ float: left; width: 100px; margin-right: 20px; //形成20px的间隔 } .right{ overflow: hidden; //通过设置overflow: hidden来触发BFC特性 }
这个方法主要是应用到BFC的一个特性:
浮动元素的块状兄弟元素会无视浮动元素的位置,尽量占满一整行,这样该兄弟元素就会被浮动元素覆盖。
若浮动元素的块状兄弟元素为BFC,则不会占满一整行,而是根据浮动元素的宽度,占据该行剩下的宽度,避免与浮动元素重叠。
浮动元素与其块状BFC兄弟元素之间的margin可以生效,这将继续减少兄弟元素的宽度。
并不是一定要在.right上用 overflow: hidden;
,只要能触发BFC就好了,另外在IE6上也可以触发 haslayout
特性(推荐用 *zoom: 1;
)。
由于.right的宽度是自动计算的,不需要设置任何与.left宽度相关的css,因此.left的宽度可以不固定(由内容盒子决定)。
<div class="parent"> <div class="left"> <p>left</p> </div> <div class="right"> <p>right</p> <p>right</p> </div> </div>
.parent{ display: table; width: 100%; table-layout: fixed; } .left,.right{ display: table-cell; } .left{ width: 100px; padding-right: 20px; }
这个方法是表格布局的典型运用。说真的,我也很迷惘要不要使用表格布局,毕竟已经是上个时代的产物了,虽然已经不再用 <table>
的HTML结构了,但用上相应的CSS其实思路跟以前是变化不大的。
这个方法主要是利用了表格(table)的宽度必然等于其所有单元格(table-cell)加起来的总宽度,那么只要表格的宽度一定,其中一个(或几个)单元格的宽度也一定,那么另外一个未设置宽度的单元格则会默认占满剩下的宽度,即实现自适应。
<div class="parent"> <div class="left"> <p>left</p> </div> <div class="right"> <p>right</p> <p>right</p> </div> </div>
.parent{ display: flex; } .left{ margin-right: 20px; } .right{ flex: 1; } .left p{width: 200px;}
flex布局的自适应我就不多说了,本来就是设计来自适应的,只需要用上 flex: 1;
,就能让.right分到.parent的宽度减去.left的宽度。
我个人是比较推荐用float + BFC
方案,浏览器兼容性很好,代码量也少,另外也很好理解;移动端上也可以考虑用上flex方案,不过还是那一句,注意用旧版的flex,兼容性会好一点。
说是说 “两列自适应布局” ,实际上,只要满足“只有一列是自适应”这一条件,多少列布局都行。
《The Definitive Guide to Using Negative Margins》
《前端精选文摘:BFC 神奇背后的原理》