纯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元素绝对定位,设置下top
和bottom
即可。
.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-sizing
为border-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实现自适应高度方法,欢迎各位大大批评指正。