box-flex与flex的不同,从渲染机制猜想进行深层分析,box弹性布局的不完善性以及解决方法,flex弹性布局的优点
2016-12-24 00:46

    弹性布局是CSS3的特性,在移动端兴起的当下,以及Microsoft宣布退出浏览器市场的情况下,我们可以考虑在移动端甚至PC端大范围使用弹性布局来书写我们的web页面,弹性布局会使我们的工作比以前轻松不少,有了弹性布局可以说浏览器的渲染定位更加智能了。而弹性布局有两种实现方式,一种是display:-webkit-box;一种是display:flex。面对这两种弹性盒子模型,相信不少人都有这个疑问,这两者到底有什么区别呢?我应该用哪一个呢?还是随便用哪一个都行呢?

   网上对此也有不少回答,大都是box弹性盒子有一些不兼容性什么的,flex布局是新的w3c标准,是用来代替box弹性盒子的。这些都是笼统的概念性的答案,它们并不能释然我们心中的疑问。

    通过布局栗子,我们来看看到底网上的说法是否正确,box和flex到底有什么区别,哪个更适合我们应用。

box-flxe.png

我们就拿实现这么一个单页的布局作为今天的栗子。首先我们用box弹性盒子来实现。因为是单页的,绿色的底栏高度是固定(或者说是一定的,后面都采用固定来说),黄色div的高度根据浏览器高度弹性适应。然后红色的顶栏是固定的,粉色div根据黄色div的高度弹性适应,这里就有了一个弹性布局的嵌套。最后蓝色的div宽度是固定的,褐色的div根据粉色div的宽度弹性适应。

   首先我们根据我们对box弹性盒子的基础认识来写一下我们认为能够实现上述布局的代码。

<div class='wrapper'>
<div class='inner'>
   <div class='head'>我们是头部信息</div>
   <div class='content'>
	<div class='left'>我是左侧信息</div>
	<div class='right'>我是内容右侧信息</div>
   </div>
</div>
<div class='bottom'>mooshine前端</div>
</div>

  在最外层的wrapper我们设置为fixed定位100%,100%适应浏览器的窗口。

body{margin:0;padding:0;font-family:"微软雅黑";}    
    
.wrapper{
    position:fixed;z-Index:2;
    left:0;top:0;
    width:100%;height:100%;
    display:-webkit-box;
    -webkit-box-orient:vertical;
    box-sizing:border-box;
    border:4px solid #1BABD4;
    padding:4px;
}
    
.bottom{line-height:52px;
    background:#26C75F;
    color:#fff;text-align:center;
    margin-top:4px;
 }
    
.inner{
    -webkit-box-flex:1;
    border:4px solid #F1DF46;
    padding:4px;
    box-sizing:border-box;
    display:-webkit-box;
    -webkit-box-orient:vertical;
}
    
.head{
    background:#C65123;
    color:#fff;line-height:52px;
    text-align:center;margin-bottom:4px;
}
    
.content{
    -webkit-box-flex:1;
    border:4px solid #BB74BC;
    box-sizing:border-box;padding:4px;
    display:-webkit-box;
    -webkit-box-orient:horizontal;
}
    
.right{
    width:120px;margin-left:4px;
    background:#243B83;
    text-align:center;height:100%:
}
    
.left{
    -webkit-box-flex:1;
    background:#733849;height:100%;
 }

按照box弹性盒子的特性,写出上面的css样式,left,right,是横向盒子,我们想让它的高度也是填充满,理所当然的就添加上了height:100%;属性。

ff1.png

用chrome以运行,哎,不对啊,我明明给left,right设置了高度100%,它怎么不起作用呢?别急,我们把高度100%去掉再试试。

.right{
    width:120px;margin-left:4px;
    background:#243B83;
    text-align:center;
}

.left{
    -webkit-box-flex:1;
    background:#733849;
 }

left,right改成这样后再用chrome运行一下

ff2.png

效果是出来了,可是为什么我设置了高度不起作用,去掉了高度反而起作用了啊,好晕,是浏览器中逗我玩么?

 弹性布局的一个特点是可以根据你的内容自动调整以达到弹性适应性。那么,box弹性布局得先知道其中的子元素的高度才能进行计算,

 最外层,先计算出绿色底栏的高度,然后再得到黄色div的弹性高度,这个我们是可以理解的,因为我们设置的弹性方向是vertical纵向的。

那么最内层我们设置的弹性方向是横向的,它的高度依然是占满了容器,我们可以这让认为,每一个横向的弹性布局里面都有一个内置的纵向布局,并且这个元素有一个默认的纵向box-flex:1;而且他至少有一个看不见的子元素。既然横向弹性里面有纵向的特性,那么如果我们给他设置高度100%的时候,他不是不在拥有纵向特性,而是纵向特性会先计算他的高度,自后再做弹性适应,而这个高度计算是先于弹性盒子的计算的,此时外层容器是没有高度的,所以他是得不到高度的。而它有了height:100%的高度设置,在弹性计算的时候,就会使用它先前计算得出的高度,所以就不再拥有纵向弹性高度占满容器的特性了。

 

  布局计算的先后顺序:

  文档流中的飞弹性盒子-->弹性盒子-->绝对定位-->绝对定位容器中的弹性盒子。

  box弹性盒子中低版本的火狐中还有一个问题,就是绝对定位上面不能直接使用display:box;要在内部嵌套一层div来设置display:box;

 下面我们看一下box弹性盒子的兼容语法

div{
    display:-webkit-box;-webkit-box-orient:vertical;
    display:-moz-box;-moz-box-orient:vertical;
    display:-ms-flexbox;-ms-flex-direction:column;
}
.item{
    -webkit-box-flex:1;
    -moz-box-flex:1;
    -ms-flex:1;
}

IE的写法跟主流浏览器有些差异,并且IE10+浏览器才支持box弹性盒子的布局,注意:所有浏览器支持的box弹性布局必须加前缀,都没有实现不加前缀的语法,用Firefox 50.1.0版本测试,即时不加-moz前缀,它也支持-webkit前缀的box弹性盒子属性。

下面我们用flex伸缩盒子来实现以下上面的页面布局效果。

.wrapper{
    position:fixed;z-Index:2;left:0;top:0;
    width:100%;height:100%;box-sizing:border-box;
//据说safari要加上webkit的前缀
    display: -webkit-flex;
    display:flex;flex-direction:column;
    border:4px solid #1BABD4;padding:4px;
}
.bottom{
    line-height:52px;background:#26C75F;
    color:#fff;text-align:center;margin-top:4px;
}
.inner{
    flex:1;border:4px solid #F1DF46;padding:4px;
    box-sizing:border-box;display:flex;
    flex-direction:column;
}
.head{
    background:#C65123;color:#fff;
    line-height:52px;text-align:center;
    margin-bottom:4px;
    }
.content{
    flex:1;border:4px solid #BB74BC;
    box-sizing:border-box;padding:4px;
    display:flex;flex-direction:row;
}
.right{
    width:120px;margin-left:4px;
    background:#243B83;text-align:center;
}
.left{
    flex:1;background:#733849;
}

aa.png

上面是火狐上的实现效果,跟box弹性盒子实现效果是一样,并且它的语法更一致,而且浏览器也是支持到IE10+,那么为了偷懒我们更倾向于使用flex布局,不仅仅是因为它是新的规范。

 而且给left和height加上height:100%的高度后,效果依然是正常的。这说明flex和box看起来的效果是一样的,但是它们的实现机制不同。flex定位的高度能被百分比继承。这更有利于我们实现复杂的页面。

我们把right块去掉,并且把黄框div的display:flex去掉

<div class='wrapper'>
<div class='inner'>
    <div class='head'>我们是头部信息</div>
    <div class='content'>
        <div class='left'>我是左侧信息</div>
    </div>
</div>
<div class='bottom'>mooshine前端</div>
</div>
//其他样式同上面
.content{
    flex:1;border:4px solid #BB74BC;
    box-sizing:border-box;padding:4px;
}
.left{
    background:#733849;height:100%;
}

 这时候黄色div以及不是flex元素,但他从他的父元素flex中获得了高度,我们用left可以继承这个高度。

 ffe.png

从效果可以看到,left确实继承了content的高度,height:100%起作用了。然而我们缩小浏览器大小的时候意外出现了

ffee.png

left元素的高度没有跟随变小,而放大浏览器的时候left的元素跟随变大了。

这是一个bug,chrome浏览器版本 53.0.2785.143 m ,在火狐,IE10+上没有这个bug。下载了最新的chrome浏览器,这个bug目前依然没有修复。

你可以点击这里做webkit浏览器下缩小浏览器查看此bug

所以在使用flex的时候,最好全部是flex的定位布局,不要用非flex元素继承flex元素的高度。毕竟webkit浏览器是主流浏览器。也许webkit不认为这是一个bug,而是正常行为。

通过上文实现,以栗子的方式用box和flex实现了。flex比起box还是有一定优点的,语法简单,渲染机制更符合我们的定位思想。高度可以被继承。所以以后写弹性布局首选flex,尤其是在移动端,浏览器的支持性更好。


原创文章,转载请注明来自:妹纸前端-www.webfront-js.com.
阅读(1019)
辛苦了,打赏喝个咖啡
微信
支付宝
妹纸前端
妹纸前端工作室 | 文章不断更新中
京ICP备16005385号-1