Flex弹性布局详解
简介
Flexible Box 模型,通常被称为 flexbox弹性盒子布局,是一种一维的布局模型。它给 flexbox 的子元素之间提供了强大的空间分布和对齐能力。
我们说 flexbox 是一种一维的布局,是因为一个 flexbox 一次只能处理一个维度上的元素布局,一行或者一列。作为对比的是另外一个二维布局 CSS Grid Layout(网格布局),可以同时处理行和列上的布局。
flexbox 的两根轴线
当使用 flex 布局时,首先想到的是两根轴线 — 主轴和侧轴。主轴由 flex-direction 定义,另一根轴垂直于它。我们使用 flexbox 的所有属性都跟这两根轴线有关,所以有必要在一开始首先理解它。
主轴
主轴由 flex-direction 定义,可以取 4 个值:
- row:主轴为横轴,从左至右排列
- row-reverse:主轴为横轴,从右至左排列
- column:主轴为纵轴,从上至下排列
- column-reverse:主轴为纵轴,从下至上排列
如果你选择了 row 或者 row-reverse,你的主轴将沿着 inline 方向延伸。
选择 column 或者 column-reverse 时,你的主轴会沿着上下方向延伸 — 也就是 block 排列的方向。
侧轴
侧轴垂直于主轴,所以如果你的flex-direction (主轴) 设成了 row 或者 row-reverse 的话,侧轴的方向就是沿着列向下的。如果主轴方向设成了 column 或者 column-reverse,侧轴就是水平方向。
起始线和终止线
另外一个需要理解的重点是 flexbox 不会对文档的书写模式提供假设。过去,CSS 的书写模式主要被认为是水平的,从左到右的。如果 flex-direction 是 row,那么主轴的起始线是左边,终止线是右边。如果 flex-direction 是 column-reverse 那么主轴的起始线是下边,终止线是上边。
什么是弹性盒?
是一种当页面需要适应不同的屏幕大小以及设备类型时确保元素拥有恰当的行为的布局方式。引入弹性盒布局模型的目的是提供一种更加有效的方式来对一个容器中的子元素进行排列、对齐和分配空白空间。为了创建 flex 容器,我们把一个容器的 display 属性值改为 flex 或者 inline-flex。 完成这一步之后,容器中的直系子元素就会变为 flex 元素。
- 弹性盒子由弹性容器(Flexcontainer)和弹性子元素(Flexitem)组成
- 弹性容器通过设置display属性的值为flex或inline-flex将其定义为弹性容器
- 弹性容器内包含了一个或多个弹性子元素
注意:弹性容器外及弹性子元素内是正常渲染的。弹性盒子只定义了弹性子元素如何在弹性容器内布局。
flex 容器中的所有 flex 元素都会有下列行为:
- 元素沿主轴排列为一行 (flex-direction 属性的初始值是 row)。
- 元素从主轴的起始线开始。
- 元素不会在主维度方向拉伸,但是可以缩小。
- 元素被拉伸来填充侧轴大小。
- flex-basis 属性为 auto。
- flex-wrap 属性为 nowrap。
这会让你的元素呈线形排列,并且把自己的大小作为主轴上的大小。如果有太多元素超出容器,它们会溢出而不会换行。如果一些元素比其他元素高,那么元素会沿侧轴被拉伸来填满它的大小。
外部flex大容器的属性设置
说明:以下描述是假设 flex-direction 为 row; 来进行的
1.display: flex/inline-flex;
- flex:将对象作为弹性伸缩盒显示
- inline-flex:将对象作为内联块弹性伸缩盒显示
2.flex-direction (设置主轴)
- row:默认,横向一行排列
- row-reverse:反转横向排列
- column:纵向排列
- column-reverse:反转纵向排列
3.justify-content(主轴对齐方式)
- flex-start:默认,顶端对齐
- flex-end:末端对齐
- center:居中对齐
- space-between:两端对齐,中间自动分配
- space-around:自动分配距离
*默认:元素在主轴上容不下不会换行,会被压缩
4.flex-wrap设置换行
- nowrap:容器为单行,该情况下子项可能会溢出容器
- wrap:容器为多行,子项内部会发生断行
- wrap-reverse:反转多行排列
5.align-items (侧轴对齐方式,适合单行)
- flex-start:侧轴起始边界
- flex-end:侧轴结束边界
- center:居中放置
- baseline:基线对齐
- stretch:默认值,项目被拉伸以适应容器
6.align-content (侧轴行与行之间对齐方式,适合多行)
- flex-start:没有行间距
- flex-end:底对齐没有行间距
- center:居中没有行间距
- space-between:两端对齐,中间自动分配
- space-around:自动分配距离 stretch 默认值,项目被拉伸以适应容器
简写 flex-flow: column warp;
你可以将两个属性 flex-direction 和 flex-wrap 组合为简写属性 flex-flow。第一个指定的值为 flex-direction ,第二个指定的值为 flex-wrap.
flex容器内部子元素的属性设置
可用空间分配
在考虑这几个属性的作用之前,需要先了解一下 可用空间 available space 这个概念。这几个 flex 属性的作用其实就是改变了 flex 容器中的可用空间的行为。同时,可用空间对于 flex 元素的对齐行为也是很重要的。
假设在 1 个 500px 的容器中,我们有 3 个 100px 宽的元素,那么这 3 个元素需要占 300px 的宽,剩下 200px 的可用空间。在默认情况下,flexbox 的行为会把这 200px 的空间留在最后一个元素的后面。
如果期望这些元素能自动地扩展去填充满剩下的空间,那么我们需要去控制可用空间在这几个元素间如何分配,这就是元素上的的三个 flex
属性要做的事。
1.flex-basis(子元素项目的长度)
flex-basis 定义了该元素的空间大小(the size of that item in terms of the space),flex 容器里除了元素所占的空间以外的富余空间就是可用空间 available space。 该属性的默认值是 auto 。此时,浏览器会检测这个元素是否具有确定的尺寸。 在上面的例子中,所有元素都设定了宽度(width)为 100px,所以 flex-basis 的值为 100px。
如果没有给元素设定尺寸,flex-basis 的值采用元素内容的尺寸。这就解释了:我们给只要给 Flex 元素的父元素声明 display: flex ,所有子元素就会排成一行,且自动分配小大以充分展示元素的内容。
2.flex-grow(为子元素分配剩余空间)
flex-grow 若被赋值为一个正整数, flex 元素会以 flex-basis 为基础,沿主轴方向增长尺寸。这会使该元素延展,并占据此方向轴上的可用剩余空间(available space)。如果有其他元素也被允许延展,那么他们会各自占据可用空间的一部分。
如果所有元素设定 flex-grow 值为 1,容器中的可用空间会被这些元素平分。它们会延展以填满容器主轴方向上的空间。
flex-grow 属性可以按比例分配空间。如果第一个元素 flex-grow 值为 2,其他元素值为 1,则第一个元素将占有 2/4(上例中,即为 200px 中的 100px), 另外两个元素各占有 1/4(各 50px)。
3.flex-shrink (子元素收缩)
flex-grow属性是处理 flex 元素在主轴上增加空间的问题,相反flex-shrink属性是处理 flex 元素收缩的问题。如果我们的容器中没有足够排列 flex 元素的空间,那么可以把 flex 元素flex-shrink属性设置为正整数来缩小它所占空间到flex-basis以下。与flex-grow属性一样,可以赋予不同的值来控制 flex 元素收缩的程度 —— 给flex-shrink属性赋予更大的数值可以比赋予小数值的同级元素收缩程度更大。
在计算 flex 元素收缩的大小时,它的最小尺寸也会被考虑进去,就是说实际上 flex-shrink 属性可能会和 flex-grow 属性表现的不一致。
flex 属性的简写
你可能很少看到 flex-grow,flex-shrink,和 flex-basis 属性单独使用,而是混合着写在 flex 简写形式中。 Flex 简写形式允许你把三个数值按这个顺序书写 — flex-grow,flex-shrink,flex-basis。
flex: 0 1 auto;
4.align-self (弹性容器内单个项目的对齐方式)
可重写弹性容器的align-items属性
- auto:默认值,元素继承了它的父容器的align-items属性
- stretch:元素被拉伸以适应容器
- center:元素位于容器的中心
- flex-start:元素位于容器的起始线
- flex-end:元素位于容器的终止线
5.order(子元素排序优先级)
数字越大越往后排,默认为0,支持负数
flex布局对行内子元素的影响
设为 Flex 布局以后,子元素的 float、clear 和 vertical-align 属性将失效;如果子元素为行内元素,可以设置宽高