纯css实现自适应高

偶尔在网上看到的一个面试题,大概描述是:

有一个可以自适应的div,里边有两个div,一个div是高度固定的,怎么实现另一个div的高度自适应剩余高度?

当然方案会有好多,可以使用js,也可以用CSS3,也可以用CSS2.1来实现;达到结果有很多种,最大的区别应该就是兼容性了。

这里大概列出几种方法,当然几种方法兼容性还是不一的;这里算是仅供参考吧,毕竟在大部分高级浏览器里,例如:Chrome(最近),Firefox(最近),IE10+,IE8~9(利用CSS3的flex的不支持)。

首先说下基本HTML结构:

<div class="Bdy">
	<div class="head"></div>
	<div class="autoHeight"></div>
</div>

也就是外边div是Bdy,然后里边两个div分别是head和’autoHeight’。下边就是在不改变整体结构的前提下实现所需的效果。所有的效果参见 CSS实现自适应高度

方法一:利用绝对定位

这种方法是我们首先想到的,父级元素相对定位,需要autoHeight元素绝对定位,设置下topbottom即可。

.Bdy {position:relative;float:left;height:100%;width:100px;margin-right:5px;background:#999;}
.head {height:50px;background:#fff;}
.autoHeight {top:50px;bottom:0;left:0;position:absolute;width:100%;background:#129B19;}

对应的实例就是效果页面中的第一列。

方法二:利用浮动

这种方法其实真正的自适应高度元素和父级元素的高度是相同的,只不过是把固定高度的元素head给浮动了,然后就不会影响后边的autoHeight元素的排列了。

.Bdy2 .head {float:left;width:100%;}
.Bdy2 .autoHeight {position:static;width:auto;height:100%;}

这里你可能会有个疑问,固定高度元素head浮动了,然后autoHeight中内容为什么是排在了head的下边,而不是和head重叠了?

可以这样考虑,如果说autoHeight元素这一层去掉,然后head元素后边紧跟着内容的话,那内容就会在head之后显示了,其实和autoHeight没啥关系,这里仅仅只是加了autoHeight包裹住了下边的内容,看起来像是达到了咱们需要的效果。关于浮动可以参见 可视化格式模型 中关于浮动的段落,或者其他关于浮动的文章。

方法三:利用负margin + overflow:hidden

这种方法和方法二一样,autoHeight元素的高度其实是和父级元素高度是一样的。

首先head的高度是一定的,然后利用负margin,这里是margin-bottom,中和掉head本身位置;之后的autoHeight元素会贴着父级元素的顶部,为了让上边空出head的高,咱们需要给autoHeight元素设置margin-top值,值的大小就是head元素高度。由于设置了margin-top,所以autoHeight元素就会超出父级元素,这时设置下父级元素overflow:hidden,这样就不会超出了。

.Bdy3 {overflow:hidden;}
.Bdy3 .head {margin-bottom:-50px;}
.Bdy3 .autoHeight {position:static;width:auto;height:100%;margin-top:50px;}

方法四:利用负margin(或绝对定位) + box-sizing:border-box

这种方法和方法三很像,同样是中和掉head元素本身占位,有两种方法:负margin和绝对定位。

然后autoHeight元素设置box-sizing:border-box,但是这样的话,autoHeight元素就会覆盖在head元素之上,所以需要让其显示出来,也就是让head的层级更高,怎么办?加上position:relative即可。这样是对了,但是这样了之后,发现head盖住了autoHeight元素了,咦。。那岂不是没辙了,等等,这就是咱们设置autoHeight元素的box-sizingborder-box发挥作用的时候了,咱们给autoHeight元素加上padding-top,值为head元素高,这样不就没问题了。

.Bdy4 .head {margin-bottom:-50px;position:relative;/*position:absolute;*//*width:100%;*/}
.Bdy4 .autoHeight {position:static;box-sizing:border-box;width:auto;height:100%;padding-top:50px;}

但是注意的是box-sizing是有兼容性问题的,最新版的Firefox和Chrome都是支持的,具体兼容列表可以参见 CSS参考手册,IE8+是支持的,但是IE8不能设置min-height,设置了会怎样,自己试验下就知道了O(∩_∩)O。

方法五:利用 box-sizing:border-box + 负margin

方法四是利用给autoHeight元素设置box-sizing:border-box来实现的,这里咱们给父级元素设置box-sizing:border-box,同时设置下padding-top,值为head元素高。

这时候咱们需要把head元素给“挪”上去,实现“乾坤大挪移”,很简单,设置下margin-top的值,利用负值把他挪上去就可以了。

.Bdy5 {box-sizing:border-box;padding-top:50px;}
.Bdy5 .head {margin-top:-50px;}
.Bdy5 .autoHeight {position:static;width:auto;height:100%;}

方法六:利用 box-sizing:border-box + 绝对定位

原理和方法五是一样的,只是把head决定定位了,需要注意的是设置的top值不是head的高,而是0。

.Bdy6 {box-sizing:border-box;padding-top:50px;}
.Bdy6 .head {top:0;position:absolute;width:100%;}
.Bdy6 .autoHeight {position:static;width:auto;height:100%;}

方法七:利用 box-sizing:border-box + 相对定位 + 负margin

基本原理和方法五、六一样,但是区别就是head元素需要通过相对定位偏移上去,而且需要中和掉自身所占空间,也就是利用负margin。

.Bdy7 {box-sizing:border-box;padding-top:50px;}
.Bdy7 .head {top:-50px;position:relative;margin-bottom:-50px;}
.Bdy7 .autoHeight {position:static;width:auto;height:100%;}

方法八:利用display:table + display:table-row + display:table-row(或者display:table-cell)

怎么看起来这么麻烦呢,简单说下,就是给父级元素设置display:table;然后head元素设置display:table-row,这样能占一行;给自适应高元素autoHeight设置display:table-row或者display:table-cell,需要注意的是,如果设置了display:table-cell,里边内容会受到vertical-align的影响,所以最好可能加上vertical-align:top;

.Bdy8 {display:table;}
.Bdy8 .head {display:table-row;}
.Bdy8 .autoHeight {position:static;display:table-row;/*display:table-cell;*//*vertical-align:top;*/}

经测试在IE8+上都是OK的,但是具体算法好像CSS2.1中并没有给出,但是貌似浏览器表现结果是一样的,都是自动适应剩余高度。

方法九:利用CSS3中的display:flex

CSS3中给予我们很多新的特性,这样在布局的时候好多时候就很容易实现我们所需的效果。

这里给父级元素设置display:flex且指定方向是在列的方向上具备弹性flex-direction:column;。然后在autoHeight元素上设置flex:1,让其自动计算高度,填满剩余空间。具体可见 w3cplus上的Flexbox——快速布局神器以及如何在IE10中使用IE10中的Flexible Box(“Flexbox”)布局

.Bdy9 {display:flex;display:-ms-flexbox;flex-direction:column;-ms-flex-direction:column;/*flex-flow:column;*/}
.Bdy9 .autoHeight {position:static;flex:1;-ms-flex:1;}

这里就不考虑老的Flexbox的写法了,具体参见w3cplus上的教程就好。

再次附上效果页CSS实现自适应高度

上面就是我所想到的CSS实现自适应高度方法,欢迎各位大大批评指正。

发布于: 2014年 10月 24日