汐辰  +

优雅的flexbox,web布局的必然趋势

1. 背景及介绍

1.1 背景

到目前为止,总共有三个版本(如下),那下边主要是根据最新版本的语法来展开讲解

  • 旧版本(Old),2009版本,使用display:box
  • 混合版本(Hybrid),2011年版本,使用display:flexbox
  • 最新版本(Modern),使用display:flex

1.2 介绍

CSS2.1总共定义了四种布局模式:

  • block布局:为文档(document)布局模式
  • inline布局:为文本布局模式
  • table布局:为以表格形式的2D数据的布局模式
  • position布局:能够明确地定位元素的布局模式

那CSS3引入flexbox的主要思想,是让容器有能力让其子项目能够改变其width,height,甚至order,以合理的方式填充可用空间,这在不同屏幕大小和不同设备上非常实用,所以可以说,flexbox就是为如今大型或者复杂应用而设计的。

2. flexbox模型

flexbox不是一个属性,他是一个模块,该模块扩展了CSS2.1中display属性的定义,添加了新的block-levelinline-leveldisplay类型,所以要定义一个flexbox容器,可以是一个元素display属性值为flex,也可以是inline-flex.而且在flexbox模型,布局计算方式也inline,block不同,后两者是偏向使用书写模式的,而flexbox则是偏向使用伸缩流方向.这块介绍一下相关的术语.

flexbox

伸缩容器 既然一个盒模型,首先它得有一个容器,元素display属性值为flex或者inline-flex就是伸缩容器.

伸缩项目 容器里的每个子元素都是这个容器的伸缩项目

主轴(main axis) flex容器的主轴,伸缩项目(flex items)主要沿着这条轴进行排列布局

主轴起点(main-start) 主轴终点(main-end) 伸缩项目放置在flex容器内从主轴起点(main-start)向主轴终点(main-end)方向

主轴尺寸(main size) 一个伸缩项目的宽度或高度,它是在主轴维度(main dimension)里面的,且是项目的主尺寸。伸缩项目的主尺寸属性是宽度或高度属性,它是在主轴维度(main dimension)里面的。

侧轴(cross axis) 垂直于主轴称为侧轴。它的方向主要取决于主轴方向

侧轴起点(cross-start) 侧轴终点(cross-end) 伸缩行的配置从容器的侧轴起点边开始,往侧轴终点边结束

侧轴尺寸(cross size) 一个伸缩项目的宽度或高度,它是在侧轴维度(main dimension)里面的,且是项目的主尺寸。伸缩项目的侧轴尺寸属性是宽度或高度属性,它是在侧轴维度(main dimension)里面的。

3. flex容器和项目的属性

flexbox模型下的属性比较多,这块不再这里陈述,为了更快速直观地了解其下边的属性的用法,请参考下边的demo.

flexbox-demo

4. 伸缩性原理

伸缩布局的特性就是让伸缩项目具有可伸缩的能力,即其宽度或高度自动填充伸缩容器额外的空间,那么这可以用flex属性来完成.如下图,flex属性有3个值,分别代表着扩展比率,收缩比率以及伸缩基准值,当一个元素是伸缩项目时,flex属性将代替主轴长度属性决定元素的主轴长度.

flex-method

那么,伸缩项目是怎么以最佳方式进行伸缩的呢?这里根据上图介绍一个伸展的例子

比如上图的伸缩容器的主轴长度是480px,下边有3个伸缩项,第二张图由于3个子项flex-grow都是0,所以不具有伸展性,所以它们在主轴里的宽度就是它们的flex-basis值.再看第三张图,把它们的flex-grow改为3,2,1之后,那么这个时候容器里边的多余空间就会按照这个比例分别分配给3个子项,每个子项增加的宽度=container_blank ×(grow/sum(grow)),最终它们在容器占用的空间就是grow_width+flex-basis.再假如我们把flex-basis设为0,那么flex-grow的比例就是它们自身空间在容器里边的比例值,而不是增长的那部分的比例.

同理,收缩比例值也是类似的计算方法,但是还是稍有不同,原因是在减的时候,如果只计算赋予的flex-shrink值,那么很有可能最后减少的宽度比 basis 大,于是子项的宽度就变成负值。所以计算的时候得把flex-basis也带进去,最终的公式就是 shrink_width = container_blank ×(shrink×basis/sum(shrink×basis))

5. 用它能做什么呢

完美居中,等高布局,双飞翼布局...都可以用它来做 这里列几个demo,均分别用传统方法和flexbox的方式来实现,试了之后会发现,用flex来实现远比传统方法优雅简单地多.

双飞翼布局

  <style type="text/css">
  *{font-size: 15px;color: gray;}
  .flex-wrap{
    box-shadow: 0 0 5px #ccc;
    padding: 8px 0 8px 0;
    border-radius: 5px;
    display: -webkit-flex;
    display: flex;
  }
  .flex-left{
    text-align: right;
    padding-left: 10px;
    line-height: 30px;
    }
  .flex-right{
    padding-right: 10px;
    text-align: right;
    line-height: 30px;
    }
  .flex-center {
      -webkit-flex: 1;
      flex: 1;
      border: none;
      outline: none;
      line-height: 30px;
      margin-left: 10px;
      border-bottom: 1px solid #ccc;
    }
  </style>
  <div class="flex-wrap">
  <label class="flex-left">用户名:</label>
  <input class="flex-center" type="text" />
  <label class="flex-right">(2-20个汉字)</label>
  </div>

等高布局

  <style>
  .flex-wrap{
          width: 900px;
          margin: 10px auto;
          display: flex;
          align-items: stretch;
      }
      .flex-left{
          width: 200px;
          background: red;
          float: left;
      }
      .flex-right{
          width: 700px;
          background: yellow;
          float: right;
      }
  </style>
  <div class="flex-wrap">
      <div class="flex-left">
          页面内容
              <br/> 页面内容
              <br/> 页面内容
              <br/> 页面内容
              <br/> 页面内容
              <br/> 页面内容
              <br/> 页面内容
              <br/>
      </div>
       <div class="flex-right">
              页面内容
              <br/> 页面内容
              <br/> 页面内容
              <br/> 页面内容
              <br/> 页面内容
              <br/> 页面内容
              <br/> 页面内容
              <br/> 页面内容
              <br/> 页面内容
              <br/> 页面内容
              <br/> 页面内容
              <br/> 页面内容
              <br/> 页面内容
              <br/> 页面内容
              <br/>
          </div>
  </div>

浏览器支持

这里有一个神奇的现象,就是这三个版本的任意一个版本单独拿出来,浏览器对它的兼容性都不是很乐观,但是把他们混合一块用,却能看到相当不错的兼容性,除了IE比较蛋疼,几乎完美兼容其他浏览器了,这么看得话,似乎在移动端现在也还是可以尝试的.即便现在兼容性上还存在问题,但是我相信flexbox必是未来布局的趋势.

browser

Blog

Opinion

Extract

Fork me on GitHub