多列布局可分为:1、定宽+自适应布局 2、不定宽+自适应布局 3、等分布局 4、等高布局。我们现在先来探讨第1、2种布局。
如何实现定宽+自适应布局?先来考虑单列定宽+单列自适应。假设parent元素,下面有left和right两个块级元素,我们要实现left宽度为80px, right自适应宽度,并且left与right水平间距为20px。点击查看固宽+自适应布局。
定宽+单列自适应布局可以有如下几种方式:1、设置left元素float:left; 并设置right的margin-left;该方法存在一个“bug”-当right中子元素设置了清除浮动后,right会整体下移。解决方法是,用一个container将right包裹起来,并设置container左浮动,宽度为100%,然后使用margin-left将容器上移。由于parent的两个子元素都是浮动元素,在浮动元素内部设置clear:both,不会影响外部布局。由于right浮动元素盖在了left元素上,导致无法选中left元素中的文本,可以设置left元素position: relative提高其层级。关于为何可以通过设置position:relative提高元素层级,参考张鑫旭的深入理解CSS中的层叠上下文和层叠顺序。
2、设置left元素float:left; 设置right的overflow:hidden。这里是利用了BFC(块级格式化上下文),参考关于Block Formatting Context--BFC和IE的hasLayout。简单来说就是,当设置right的overflow:hidden后即生成了一个BFC,一个BFC就是页面上的一个独立容器,它不与外面的浮动元素发生重叠,也即遇到浮动元素后就会自动收缩。打个比方就是,BFC就像是有内涵又有点羞涩的汉子,float元素就像柔情似水的菇凉,当某天BFC汉子碰到float妹子,就会不由自主的缩起身子,与菇凉保持似近非近的距离。如果float没有设置margin-right,则默认BFC与float是肩碰肩,所以,如果float菇凉觉得距离太近,可以设置其margin来控制与BFC汉子的距离。
3、使用table,设置parent的display:table,并设置其宽度width: 100%; 然后设置left,right元素display: table-cell。当给left设置宽度width: 80px后,right默认宽度为table剩余宽度。由于table-cell是无法设置margin的,我们可以通过设置padding来为table-cell元素间保留空隙。为了提高渲染速度,我们还会给parent设置table-layout: fixed。
4、使用强大的flex。设置parent的display: flex;此时left,right变为flex-item,他们的宽度与内容自适应。现在给left设置宽度width: 80px; 并设置其margin-right: 20px; 设置right的flex:1;后right占据flex元素剩余宽度。由于flex自适应内容的灵活性,大范围使用flex会影响浏览器性能,所以我们通常使用flex做一些小范围的布局。
那么如何实现定宽(n)+自适应呢?方法与单列定宽+自适应类似。
现在,我们来看看如何实现不定宽+自适应。
不定宽+自适应可以说是定宽+自适应的拓展,区别在于,不定宽元素的宽度可以改变。我们可以试着从定宽+自适应的方法中寻找我们要的解决方法。我们的筛选条件是,自适应元素(right)与定宽(left)元素的宽度无关,也就是说,right元素可以自动调整与left元素的举例。上述4中方法中符合这个条件的分别是第2、3、4种方法。
方法2、float+overflow。设置left的float:left;使得left元素宽度自适应,right元素由于设置了overflow:hidden;默认与left元素挨着而不重叠。left使用margin控制与right的距离。
方法3、设置parent的display: table;子元素display: table-cell;我们的目标是left元素自适应内容宽度,right元素为table剩余宽度,那么如何实现呢?我们可以将left的width设置得足够小,为0.1%,为什么是0.1%,而不是1px呢?这主要是出于在ie8中的兼容性考虑。然后我们给left里面的文本元素设置一个宽度,使得left中的内容将left撑开,由于left的宽度足够小,所以right会占满它所能占有的全部宽度。这里要注意,不能给parent设置table-layout:fixed,因为这样会使得布局固定,left无法被内容撑开,right宽度近似为table宽度。现在我们再探究一下table-cell默认宽度。若不给table下的table-cell设置宽度table-cell默认宽度根据内容平分,例如,如果left元素中内容为字符“A”,right元素中内容为字 符“B”,那么left与right的宽度相等,若left元素中内容改为“AB”那么,left的宽度为right的两倍。当给parent元素设置 table-layout: fixed后,table-cell元素的默认宽度与内容无关,而是固定的,若未给table-cell设置宽度,table-cell元素默认平分 parent宽度。
方法4、依旧是强大的flex,flex-item默认宽度为内容宽度,只需给parent设置display: flex;然后right的flex: 1;即可使得right默认填满parent剩余空间。
参考:网易前端微专业布局课程。