FLEX布局的一些问题和解决方法
前言
露珠最近研究了一下flex的布局方式,发现项w3c推出的这套布局解决方案对于日益复杂的前端开发布局来说是确实是一利器,并且在不同的屏幕上实现了真正的响应式布局:不再单纯地依赖百分比和float的强拼硬凑来达到设计需求,在各个屏幕上显示效果友好,弹性的伸缩元素,简洁易维护的代码。只可惜,这位老兄有一位致命的缺点----除了chrome外几乎所有手机上浏览器都没有兼容它!!,或者支持程度大不一样!这样开发人员头疼的问题就来了,刚刚在手机上忽略掉IE这个强盗的兼容问题,又来一个?!。flex的优势那么多,但是如果浏览器不兼容的话也是没法子用的。很多人会选择放弃它。在最初面对这样的问题的时候我是拒绝的,他们说要加兼容特技,我说我不用,还是absoute布局爽。但是!duang一下,露珠怀着人不学不知义的想法,想到google旗下产品(chrome、安卓等)在前端界的地位,相信不久各大浏览器厂商都会像标准靠齐。所以flex是要学习的,不过在这之前我们可以用替代方案解决它。本篇文章将对新(felx)旧(flex-box)两种布局方式对比。由于网上关于flex布局方式的介绍已经很多,本文不会对flex做详细介绍,主要分享一下用旧方式(box)解决flex移动端的兼容问题。首先我们写一个flex的例子,展示一下他的部分属性。
一个小示例
手机端一张卡片列表,高度100像素,全屏宽,左边圆角图片(box1),中间三行介绍,上中下均分卡片高度,中间(box2)自适应分配剩余长度,最右边按钮(box3)。我们分别用几个盒子代表定位的元素来简单实现该需求。HTML结构的代码如下:
<div class="box"> <div class="box1">red</div> <div class="box2"> <div class="item1">green</div> <div class="item2">blue</div> <div class="item3">gray</div> </div> <div class="box3">orange</div> </div>
实现效果大概是下面那样的:
普通定位的实现
思路大概是这样的:由于要实现中间的盒子box2长度适应拉伸,百分比是不可以做到的。所以采用box1和box3绝对定位,box2不设置宽度,分别设置左边距(box1的宽度+box1到外框的宽度+box1到box2的间距)和右边距(box3宽度+box3到外框的宽度+box3到box2的间距);由于三个box都需要垂直居中,所以为最外面的box设置一个百分比padding,即使如此也很难再外框高度拉伸的时候让所有元素垂直居中。况且每个盒子的高度是固定(不是按照百分比)的而且是不一样的。所以这样的方式只能只有尽可能的接近效果,前提是外框高度不变情况下。如果需要垂直居中,可以用table布局,但是,诸位并不像因为一个这样的居中属性而去改变整个块的布局方式吧?至于里面的三块子盒子,则是按照外边距来平均分布在box2中,下面是大概的伪代码,不全列出来:
.box { position: relative;/*外框定位*/ padding: x% 0; } .box1 { position: absolute; left: 10px; } .box2 { padding-left: box1.width + box1.left + box2.margin-left;/*box2的左内边距*/ padding-right: box3.width + box3.right + box2.margin-right;/*box的右边距*/ } .box2.div{ margin-bottom: x%;/*box2内的元素排列*/ } .box3 { position: absolute;/*外框定位*/ right: 10px;/*外框定位*/ }
用普通的方式最难解决的是高度适应的问题,也就是在高度固定时元素垂直居中的问题。其次是中间元素剩余空间的分配。这还只是个很简单的例子,如果遇上更加复杂的布局,要兼容调整的就不只一点代码能解决了。
flex布局解决方案:
felx采用的是弹性布局,在声明一个元素的display属性为flex的时候,浏览器在元素内计算两天轴来,两条方向轴根据flex-direction属性的值决定是纵轴位主轴还是横轴为主轴。在这里,我们给box 设置felx属性,并且将其X轴设置为主轴。然后让里面的元素在副轴上(Y轴纵轴)上居中。为了设置box2分配剩余空间,我们给box2的flex属性设置为auto:意思是扩大和缩放都在box2上。然后我们将box2的display属性也设置为flex,为了均匀排列里面的元素,可以将box2的主轴设置为Y轴,然后再Y轴上设置均分属性:justify-content: space-between;我们看下伪代码:
.box { display: flex;/*申明布局方式*/ flex-direction:row;/*声明主轴的方向*/ justify-content:flex-start;/*主轴的排列*/ align-items:center;/*副轴排列*/ } .box2 { flex-direction: column; justify-content: space-between; align-items: flex-start; flex: auto;/*自适应填充方式*/ }
简简单单几行代码,实现了普通布局花了2倍的代码量完成的需求。而且不管高度宽度如何变化,里面的元素排列一直整整齐齐。当然在复杂的布局中省掉的不仅仅使代码量,而且还有维护成本等一系列的开销。这就是flex的优势所在。但是致命缺陷马上就要暴露,在手机端查看,却出现了另一个鬼样子(完全错乱的排列顺序)。这让露珠很失望很失望。欣喜若狂的赶脚马上烟消云散。下面我们就要寻找兼容的解决的方案。
兼容版本box布局
据露珠所知,box布局方式是flex的前辈了,属于老一代的解决方案。在w3c里面已经列为了标准。也就是说只要加上前缀,它就能被各个浏览器支持。下面我们就用此方法兼容一下手机浏览器。
.box{ display: -webkit-box;/*布局方式 相当于display:flex*/ -webkit-box-align: center;/*box的对齐方式 align-items:center;*/ } .box2{ display: -webkit-box; -webkit-box-orient: vertical;/*排列方式flex-direction: column*/ -webkit-box-pack: justify;/*box2的纵向排列方式 justify-content: space-between;*/ -webkit-box-flex:1; /*box2的伸缩比例 flex:auto;*/ }
以上代码就是老旧版本的兼容写法,虽然说它老,但是却被各种浏览器兼容。通过测试,在chrome、安卓、ios上样式和排列都是正常的。到此为止,我们做的小小的兼容示例就完成了!
小结
这是目前露珠在使用flex上遇到的一些兼容问题和解决的方案。实际上在实施过程中遇到的情况比此处更复杂。露珠也借助了flex学习了一下box布局,发现box布局早已有之,在国外已经被普遍使用,而吾等竟全然不知。每念及此,无不垂足顿胸,蹲守顿足啊。同时,希望露珠这篇文章能激发你学习新布局技术的动力。在前端这条路上,即使原地不动也算是退步。