flexbox
CSS 弹性盒子布局是 CSS 的模块之一,定义了一种针对用户界面设计而优化的 CSS 盒子模型。在弹性布局模型中,弹性容器的子元素可以在任何方向上排布,也可以“弹性伸缩”其尺寸,既可以增加尺寸以填满未使用的空间,也可以收缩尺寸以避免父元素溢出。子元素的水平对齐和垂直对齐都能很方便的进行操控。通过嵌套这些框(水平框在垂直框内,或垂直框在水平框内)可以在两个维度上构建布局
怎么使用flexbox
通过设置
display
属性的值为flex
或inline-flex
来定义弹性容器
1 | .box { |
1 | <div class="box"> |
理解 flexbox 的两根轴线
当使用 flex 布局时,首先想到的是两根轴线 — 主轴和交叉轴。主轴由 flex-direction
定义,另一根交叉轴垂直于它。我们使用 flexbox 的所有属性都跟这两根轴线有关, 所以有必要在一开始首先理解它。
主轴
主轴由 flex-direction 定义,可以取4个值:
- row
- row-reverse
- column
- column-reverse
如果你选择了 row
或者 row-reverse
,你的主轴是左右方向即横向。
选择 column
或者 column-reverse
时,主轴会变成沿着上下方向延伸即纵向。
交叉轴
交叉轴是垂直于主轴,所以如果你的flex-direction (主轴) 设成了 row 或者 row-reverse 的话,交叉轴的方向就是上下方向(纵向)。
如果主轴方向设成了 column 或者 column-reverse,交叉轴就是横向。
理解主轴和交叉轴的概念对于对齐 flexbox 里面的元素是很重要的;flexbox 的特性是沿着主轴或者交叉轴对齐之中的元素。
起始线和终止线
这里解释一下为什么不用左右来描述flex元素的方向。
因为在不同语言中,例如英语和阿拉伯文他们的书写方向是不一样的,过去,CSS的书写模式主要被认为是水平的,从左到右的。现代的布局方式涵盖了书写模式的范围,所以flex不再假设你是用什么语言。
下面在解释一下英语和阿拉伯文的书写顺序:
如果 flex-direction 是 row ,并且我是在书写英文,那么主轴的起始线是左边,终止线是右边。
如果我在书写阿拉伯文,那么主轴的起始线是右边,终止线是左边。
在这两种情况下,交叉轴的起始线是flex容器的顶部,终止线是底部,因为两种语言都是水平书写模式。
flex 容器
当添加display: flex || inline-flex,容器就变成flex容器,而它的子元素变成了flex元素,所有CSS属性都会有一个初始值,所以 flex 容器中的所有 flex 元素都会有下列默认行为:
- 元素排列为一行 (flex-direction 属性的初始值是 row)。
- 元素从主轴的起始线开始。
- 元素不会在主维度方向拉伸,但是可是缩小。
- 元素被拉伸来填充交叉轴大小。
- flex-basis 属性为 auto。
- flex-wrap 属性为 nowrap。
flex 容器属性
flex-direction
确立主轴
初始值:row
flex-direction: row;
// 主轴为水平线,起始线在左,终止线在右
flex-direction: row-reverse;
// 主轴为水平线,起始线在右,终止线在左
flex-direction: column;
// 主轴为垂直线, 起始线在上,终止线在下
flex-direction: column-reverse;
// 主轴为垂直线,起始线在下,终止线在上
请注意,
dir 属性
会把 row 和 row-reverse 的 flex 容器的起始线和终止线的影响。 如果它的dir 属性
是 rtl,row 表示起始线在右,终止线在左,而 row-reverse 表示起始线在左,终止线在右;
flex-wrap
指定 flex 元素单行显示还是多行显示
初始值:nowrap
flex-wrap: nowrap
// flex元素被摆放到到一行,这可能导致溢出 flex 容器flex-wrap: wrap
// flex元素被打断到多个行中flex-wrap: wrap-reverse
// 和wrap值一样,但是 交叉轴的start 和 交叉轴的end 互换。
flex-flow
初始值: row nowrap;
CSS flex-flow 属性是 flex-direction 和 flex-wrap 的简写。
justify-content
定义主轴如何排布。
初始值:flex-start
1 | /* 位置对齐 */ |
当 length 属性和自动外边距属性(margin: auto)生效之后,对齐已经完成了。也就是说,如果存在至少一个弹性元素,而且这个元素的 flex-grow 属性不等于 0,那么对齐方式不会生效,就像没有多余空间的情况
align-items
定义交叉轴如何排布。
初始值:stretch
align-items属性以与justify-content相同的方式在侧轴方向上将当前行上的弹性元素对齐。
1 |
|
align-content
对交叉轴中围绕flex元素的盒子进行分配空间
初始值:stretch
该属性对单行弹性盒子模型无效。
1 | align-content: stretch; |
align-items 与 align-content 区别
与align-content属性的区别在于align-items指定了当前Flex容器的每行项目的对齐方式,而align-content则指定了行整体的对齐方式
flex 元素
flex 元素属性
order
规定了flex容器中的flex元素的顺序,元素按照 order 属性的值从小到大的顺序进行布局。拥有相同 order 属性值的元素按照它们在源代码中出现的顺序进行布局。
初始值:0
align-self
定义了单个弹性项目在交叉轴上应当如何对齐,这个定义会覆盖由 align-items 所确立的默认值。
如果任何 flex 元素的侧轴方向 margin 值设置为 auto,则会忽略 align-self。
初始值: auto
1 | align-self: auto // 设置为父元素的 align-items 值,如果该元素没有父元素的话,就设置为 stretch。 |
flex-grow
flex-grow
:
可理解成flex元素占据主轴剩余空间的比例。
拉伸的结果是:原始宽度 + 占据剩余宽度
若flex容器width为400px
,容器内有3个flex元素width为100px
,这时
当对第三个元素添加flex-grow:1,此元素width会扩展剩余的空间,因为其他两个元素默认flex-grow为01
2
30 + 0 + 1 = 1;
1/1 = 1 * 100px(剩余空间) = 100px;
100px + 100px = 200px
,第三个元素占100%比例(占用剩余的空间比例),最终结果为200px
。
若把第二个元素也添加flex-grow:1,此时1
2
3
40 + 1 + 1 = 2;
1/2 = 0.5
0.5 * 100 = 50px
100px + 50px = 150px
,第二、三元素各占剩余空间的50%宽度。最终结果各为150px
。
flex-shrink
flex-shrink:属性指定了 flex 元素的收缩规则。
flex 元素仅在默认宽度之和大于容器的时候才会发生收缩,其收缩的大小是依据 flex-shrink 的值。
假如flex容器是400px,现在有5个子元素分别都是100px如下面算法:
每个元素flex-shrink默认为1:
5 * 100 = 500 - 400 = 多出100 / 5 == 每个减20px
如果把其中一个元素改成flex-shrink:2
5 * 100 = 500 - 400 = 多出100 / 6 == 16.666666666,你为2的要减16.666666666 * 2
当 flex-shrink: 0
时,flex元素不会收缩,所以可能会出现超出容器。
flex-basis
flex-basis:指定了 flex 元素在主轴方向上的初始大小。
如果不使用 box-sizing 来改变盒模型的话,那么这个属性就决定了 flex 元素的内容盒(content-box)的宽或者高(取决于主轴的方向)的尺寸大小。
简单说与width属性类似,如果同时设置flex-basis和width,那么width属性会被覆盖掉。
1 | flex-basis: 10em; |
弹性盒子相关属性
不影响弹性盒子的属性
由于弹性盒子使用了不同的布局算法,某些属性用在弹性容器上没有意义:
- 多栏布局模块的 column-* 属性对弹性项目无效。
- float 与 clear 对弹性项目无效。使用 float 将使元素的 display 属性计为block。
- vertical-align 对弹性项目的对齐无效。