How flexbox works

属性#1 display: flex
示例如下

我们有4个不同大小的div包含在一个灰色的div父容器里,每个div都默认设置为:display: block
现在给父容器设置:

实际上我们给这4个div添加了一个 flex context (弹性上下文)
在这个弹性上下文中定位这4个div比传统的CSS要容易得多
属性#2 flex-direction
一个 Flexbox 的父容器有两个轴:主轴和交叉轴。默认情况如下:

默认情况下父容器中的每个元素都会沿着主轴自左向右依次排列。所以父容器设置为 display: flex 后所有的 div 会排列在一行上
但是 flex-direction 属性可以让主轴旋转,如下:

注意:flex-direction: column 并不是把 div 从主轴移动到交叉轴上,而是让主轴从水平变为垂直flex-direction 还有两个值: row-reverse 和 column-reverse

属性#3 justify-content
justify-content 用来控制元素在主轴上的对齐方式
先深入理解下主轴和交叉轴的区别。首先设置 flex-direction: row
justify-content 有5个可选值:
flex-startflex-endcenterspace-betweenspace-around

space-between 会使每个 div 之间产生相同的间隔,但在 div 和父容器之间没有间隔
space-around 会在每个 div 两侧各产生一个相同的间隔,即父容器和最外层的 div 之间的间隔刚好是两个 div 间隔的一半
注意:justify-content 是沿着主轴工作的。 flex-direction 改变的是主轴方向。
属性#4 align-items
如果理解了justify-content,align-items将会很容易
justify-content 是沿着主轴工作的,而 align-items 则是沿着交叉轴工作的。
首先重置 flex-direction: row 两个轴展示如下:

align-items 有5个可选值:
flex-startflex-endcenterstretchbaseline
前三个都和justify-content一样,看看后两个:
align-items: stretch: 每个 div 都会充满交叉轴
align-items: baseline: 按照 p 标签的底部对齐

注意:align-items: stretch, 每个 div 的 height 必须为 auto 否则 height 属性会覆盖 stretch 的效果
对于align-items: baseline,如果 div 内没有 p 标签或者 div 内没有文字或者子标签内没有文字将按照每个 div 的底部对齐。像这样:

为了更好的理解主轴和交叉轴的区别,把 justify-content 和 align-items 合在一起,看看在 flex-direction 两种值下的效果

属性#5 align-elf
align-self 允许你手动设置一个元素的对齐方式
这会覆盖掉元素原有的 align-items 属性。因为父容器内元素属性都为 auto, 所以每个 div 都会使用父容器的 align-items 属性值
|
|
将前两个 div 设置 align-self 属性,剩下的设置 align-items: center 和 flex-direction: row:

Even more about how flexbox works
上一节我们已经了解了Flexbox的基本属性:flex-direction, justify-content, align-items, and align-self
属性#1 flex-basis
在上一节,我们主要看了应用在container元素上的属性,这一节,我们专门来看应用在子元素上的属性
在设置其他Flexbox属性之前,flex-basis 控制元素的默认尺寸
下图表示flex-basis可以和 width 属性互换

那 flex-basis 和 width 又有什么区别呢?它与flex axes相对应:

flex-basis 是通过主轴 (main axis) 来影响元素尺寸的
保持 flex-basis 不变,然后切换主轴方向:

注意,我们必须从手动设置高度切换成手动设置宽度。根据flex-direction 的不同,flex-basis 会交替的影响 width 或 height
属性#2 flex-grow
将每个元素的 width 都设置为 120px

flex-grow 的默认值为 0,这意味着子元素不能在父容器内增长 (grow) 他们的宽度
这是什么意思呢?让我们设置每个子元素的 flex-grow: **1**:

这些子元素在父容器内均匀的充满了整个空间。flex-grow 的值覆盖了 width的值
那 flex-grow: 1 到底意味着什么呢,如果我们改为 flex-grow: 999

结果完全一样。这是因为 flex-grow 不是个绝对值——而是一个相对值。
如果我们设置每个子元素的 flex-grow: 1,然后再调整第3个子元素的 flex-grow值,看看有什么变化:

用一点简单的数学知识就可以理解:
每个子元素的 flex-grow 的初始值为1,加起来总数为6。父容器因此划分为6个单独的区域,每个子元素都占据了1/6父容器的空间
同理,设置第3个子元素的 flex-grow值为2,这时总的flex-grow值为:1+1+2+1+1+1,父容器划分为7个单独的区域,第3个子元素占据了2/7父容器的空间,剩下的每个子元素都占据了1/7父容器的空间
当设置第3个子元素的 flex-grow值为3的时候,总的flex-grow值为:1+1+3+1+1+1,父容器划分为8个单独的区域,第3个子元素占据了3/8父容器的空间,剩下的每个子元素都占据了1/8父容器的空间
实际上 flex-grow 就是一个比例关系,设置每个子元素 flex-grow: 4, 第三个子元素 flex-grow: 12, 其实和 1:3的情况是一样的

真正重要的是每个子元素的 flex-grow 和其它子元素的 flex-grow 比例关系
最后要注意的是,和 flex-basis 属性一样,flex-grow 属性也是沿着主轴工作的,子元素只改变其宽度,除非设置 flex-direction: column
属性#3 flex-shrink
flex-shrink 的作用和 flex-grow 恰恰相反,来确定一个元素的缩小比例
flex-shrink 的主要用途是指定哪些子元素要缩小,哪些子元素不缩小。flex-shrink 的默认值为1——意味着子元素会随着父容器缩小而相应缩小

现在设置第三个元素的 flex-shrink 的值为0,禁止随父容器缩小而相应缩小,因此它不会收缩到自己的宽度以下(这里它的宽度为120px),但可以增长宽度以适应父容器的宽度。
同样的,flex-shrink 也是比例关系
If one box has flex-shrink of 6, and the rest have flex-shrink of 2, the one box will shrink 3x as fast as the rest, as space compresses.
Note the wording there: the square with a 3x flex-shrink will shrink 3x as fast. This does not mean it will shrink 1/3 of the width.
属性#4 flex
flex 属性是把 flex-grow flex-shrink flex-basis 综合到了一起
默认值为 0 (flex-grow) 1 (flex-shrink) auto (flex-basis)
最后一个例子,我们简化成只有两个元素:
它们有相同的 flex-basis ,这意味着如果有足够的空间容纳它们(父容器的宽度为600px,还有margin和padding),它们都会是300px宽
元素1将会以2x的速度增长宽度,元素2将会以2x的速度缩小宽度

How Things Shrink And Grow
当元素1 (.square#one) 增长时它不会增长到元素2 (.square#two) 的两倍;同样元素2 (.square#two) 也不会缩小为元素1 (.square#one) 的一半
这是因为不是它们的大小比例为2:1或1:2,而是它们的收缩和增长速度
一点数学计算
父容器的初始宽度为640px,除去两边各 20px 的 padding 后,两个子元素的 flex-basis 为 300px
当设置父容器的宽度为 430px 时,减少了 210px 的空间, 元素1 flex-shrink: 1 减少了 70px ; 元素2 flex-shrink: 2少了 140px
当设置父容器的宽度为 340px 时,减少了 300px 的空间, 元素1 减少了 100px; 元素2 少了 200px
减少的比例正好也是 2:1
flex-grow 也是同样道理。设置父容器的宽度为 940px 时,增加了了300px的空间, 元素1增加了额外的 200 px,元素2增加了额外的 100px

Conclusion
As a final recap: flex-basis controls how large an element will be along the main-axis before any growing or shrinking occurs. Flex-grow determines how much it will grow in proportion to sibling elements, and flex-shrink determines how much it will shrink.
第一节翻译自How flexbox works — explained with big, colorful, animated gifs
第二节翻译自Even more about how flexbox works — explained in big, colorful, animated gifs