用flexbox

简介

Flexbox是一种CSS3中新的布局模式以解决现代web应用中日趋负责的需求。这篇问题希望给你一个全面的了解Flexbox。

为什么要用Flexbox?

Flexbox给了我们一个过去没有的控制布局的方式,以往是hack我们的float,clearfixed,解决inline-block中空白,添加display:table,甚至使用position:absalute拉伸content。而这些是如此的复杂,为什么不以一种更简单的方式来处理这些呢,恩,是时候了,flexbox就是致力于改变这些,是事情变得简单。
flexbox的强大之一就是计算空间的能力,在遇到不知道需要处置多少项目时这将变成一个利器。

特殊点和浏览器支持

flexbox规范已经经历了三年的发展。不同的浏览器有者不同的实现方式。12年9月三大主要的版本齐聚W3C确定一致的方案,这意味这浏览器实现的统一。
Flexbox规范时间线:
July 2009 Working Draft (display: box;) March 2011 Working Draft (display: flexbox;)
November 2011 Working Draft (display: flexbox;) March 2012 Working Draft (display: flexbox;)
June 2012 Working Draft (display: flex;) September 2012 Candidate Recommendation (display: flex;)

概念和术语

Flexbox包括Flex容器和Flex items。Flex容器使用display属性声明一个元素是flex或者inline-flex,使用flex的容器被渲染成block,使用inline-flex的渲染成inline的。如下是实例:

1
2
3
4
.flex-container {
display: -webkit-flex;
display: flex;
}

盒子模型

不像block和inline布局,他们的布局计算是基于块和文本流(block and inline flow direction),flex布局是基于flex directions,为了便于讨论flex布局,这里定义了一系列的flex flow相关的术语。’flex-flow’的值决定了如何将这些术语映射到物理方位(顶/右/底/左),轴(纵向/横向),大小(宽/高)。
sss
main axis
main 维度
main 轴是flex容器的主轴,flex items沿着他分布,并延伸。
main-start
main-end
cross axis
cross 维度
cross start
cross end

Flex容器的属性

flex-direction

flex-direction用来更改flex容器的轴。默认值是row,该值下,flex元素以writing-mode方式排列,从左到右,从上到下。
row-reverse: The Main Start 和 Main End 对换.如果 writing-mode 是从左到右, Flex Items 将从右到左排列。 column: The Main Axis 和 the Cross Axis 对换。
*column-reverse:同

justify-content

justify-content调整flex元素在main轴上的位置, 可能取值:
flex-start (default) flex-end
center space-between
*space-around
sss

align-items

align-items是相对justify-content的,调整flex元素在cross轴上的位置,可能的取值:
flex-start (default) flex-end
center baseline
*stretch
sss

align-content

align-content是修饰flex-wrap的行为的。他类似与align-item,但是不是调整Flex Item,而是调整Flex Lines的。可能的取值:
stretch (default) flex-start
flex-end center
space-between space-around

flex-flow

flex-flow是flex-direction和flex-wrap的缩写
flex-flow:[flex-direction][flex-wrap]

Flex Items的属性

Flex Item是任何Flex容器的直接子元素,Flex容器的文本也被认为是一个Flex Item

order

order用来设置Flex Items在渲染时的排列顺序。

align-self

align-self将覆盖Flex容器的align-items对单个Flex Item的影响。可能的取值:
stretch (default) flex-start
flex-end center
*baseline

flex

flex指定了各个Flex Item占用空余空间的优先级。
恩,对的,这里对于flex属性需要在详细说说,我们在查看使用flexbox布局时,常常可以看到这样子的
Flex:1 0 auto。他是三个flexbox属性的缩写,他们依次是:flex-grow,flex-shrink和flex-basis

Flex-basis和Flex-grow

Flex-basis决定了其他两个属性如何起作用,将是伸长还是缩短。他是Flex item的初始尺寸。

关于伸长

  • 2 / 0 / 100px
  • 0 / 0 / 150px
  • 2 / 0 / 50px


在上例可以看到,中间的元素没有允许伸长和缩短所以保持150px,剩余的450px的空间由其他的flexitem填充,他们同时有相同的值2,所以各分配225px。那么他是如何计算的呢?

计算空间

究竟有多少的空间分配给各个的flex item,他们的计算公式如下:

1
2
Availabel space =(container size - flex-basis siblings total)
可用空间=容器的空间大小 - 所有flex-basis的和

可用空间将用来分配为用于伸长的量。带入公式,上例中容器大小是600px,所有的单个元素的和是300px,
于是有:容器大小(600px)- 所有的元素和(300px)。

1
2
Grow unit = (Availabel space / Sum Grow siblings total).
伸长单位 = 可用空间/所有同级元素的增长和

我们的增长数字就是所有同级元素相加的结果(2 + 0 + 2 = 4).可用空间300/4 = 75。一个伸长单位是75px大小。

1
Flex item size = (Flex basis +_(Grow Unit * num))

于是最后的计算结果是item1(flex:2 0 100px)等于100px + (75 2)结果是250px,item2(flex:0 0 150px)等于150px,item3(flex:2 0 50px)等于50px + (75 2)结果是200px。我们可以将公式简化一点:

1
2
Availabel space = (Contianer size - Flex-basis siblings total).
Flex Item size = Basis + ((Availabel space / Total Grow nums) * Individual grow num).

一个四舍五入的bug

我注意到在firefox32中会以一种奇怪的方式四舍五入数字,firefox会将我的flex计算为1px而不是他应该的大小.

关于收缩