1、flexbox 简介
Flexible Box Module
,通常简称为flexbox
,被设计为一维布局模型,是一种可以提供界面中项目之间空间分配和强大对齐能力的方法。当我们将flexbox
描述为一维时,我们是在描述flexbox
一次处理一维布局的事实——无论是作为行还是作为列。这可以与CSS Grid Layout的二维模型进行对比,后者将列和行一起控制。 —— Mozilla mdn
传统的布局方案基于盒状模型,依赖 display
属性 + position
属性 + float
属性。它对于那些特殊布局非常不方便,比如,垂直居中就不容易实现。Flexbox 布局(Flexible Box)
提供一种更有效的方式来布置、对齐和分配容器中项目的空间,即使它们的尺寸是未知的、动态的(因此有 "flex"
一词)。
弹性布局背后的主要思想是让容器有能力改变其项目的宽度/高度(和顺序)
,以更好地填充可用空间(主要是为了适应各种显示设备和屏幕尺寸)。一个灵活的容器可以扩展项目以填充可用的自由空间,也可以收缩项目以防止溢出。
相对于常规布局(基于垂直方向的block
和基于水平方向的inline
),flexbox
布局是不分方向的。虽然这些常规布局对页面来说效果很好,但它们缺乏灵活性,无法支持大型或复杂的应用(尤其是在改变方向、调整大小、拉伸、缩小等方面)。
注意:
Flexbox
布局最适合于应用程序的组件,以及小规模的布局,而网格布局则是为了大规模的布局。
如果常规布局是基于块状和内联的流动方向,弹性布局则是基于 "弹性流动方向"。其中主要的概念如下图中所示:
项目将按照主轴或交叉轴进行布局:
main axis
: 弹性容器的主轴。main-start | main-end
: 弹性项目在容器的主轴方向上从main-start
开始,到main-end
进行排列。main size
: 弹性项目(flex item
)的宽度或高度,以主尺寸中的那个为准,是项目的主要尺寸。弹性项目的主要尺寸属性是“宽度”或“高度”属性,以主要尺寸中的那个为准。cross axis
: 垂直于主轴的轴被称为交叉轴。它的方向取决于主轴的方向。cross-start | cross-end
: 弹性项目在容器的交叉轴方向上从cross-start
开始,到cross-end
进行排列。cross size
: 交叉轴的宽度或高度。
浏览器支持方面,可以在 Caniuse 中看到,主流浏览器几乎都对它有很好的支持了~
2、Flex 容器(Container)属性
2.1 display
设置容器为 Flex布局
,可以取值为 flex
或 inline-flex
。
.container { display: flex; /* or inline-flex */ }
2.2 flex-direction
flex-direction
用来确定弹性容器中主轴的方向。Flexbox 是单向布局,主要以水平行布局或垂直列布局。
.container { flex-direction: row | row-reverse | column | column-reverse; }
row
(默认): 水平方向为主轴,方向为从左至右row-reverse
: 水平方向为主轴,方向为从右至左column
: 垂直方向为主轴,方向为从上至下column-reverse
: 垂直方向为主轴,方向为从下至上
主轴和交叉轴是Flex布局
中的两个重要概念。主轴是Flex容器
中子元素排列的方向,交叉轴是垂直于主轴的方向。例如,如果你设置了flex-direction: row
,那么主轴就是水平方向,交叉轴就是垂直方向。如果你设置了flex-direction: column
,那么主轴就是垂直方向,交叉轴就是水平方向。可以通过不同的属性来控制子元素在主轴和交叉轴上的对齐方式。例如,justify-content
用于设置主轴上的对齐方式,align-items
用于设置交叉轴上的对齐方式。
2.3 flex-wrap
默认情况下,弹性项目会默认尝试将全部的项目放在一行中。flex-wrap
用来设置是否换行,可以取值为nowrap(不换行)
、wrap(换行)
或 wrap-reverse(反向换行)
。
.container { flex-wrap: nowrap | wrap | wrap-reverse; }
nowrap
(默认):所有弹性项目都在一行上,可能导致容器溢出wrap
: 弹性项目将换行到多行,从上到下,方向由flex-direction
定义wrap-reverse
: 弹性项目将从下到上换行到多行,与flex-direction
定义的方向相反
下面看一个demo,来实际感受这三个属性值的区别:
<ul class="flex-container nowrap"> <li class="flex-item">1</li> <li class="flex-item">2</li> <li class="flex-item">3</li> <li class="flex-item">4</li> <li class="flex-item">5</li> <li class="flex-item">6</li> <li class="flex-item">7</li> <li class="flex-item">8</li> </ul> <ul class="flex-container wrap"> <li class="flex-item">1</li> <li class="flex-item">2</li> <li class="flex-item">3</li> <li class="flex-item">4</li> <li class="flex-item">5</li> <li class="flex-item">6</li> <li class="flex-item">7</li> <li class="flex-item">8</li> </ul> <ul class="flex-container wrap-reverse"> <li class="flex-item">1</li> <li class="flex-item">2</li> <li class="flex-item">3</li> <li class="flex-item">4</li> <li class="flex-item">5</li> <li class="flex-item">6</li> <li class="flex-item">7</li> <li class="flex-item">8</li> </ul>
会发现 wrap
和 wrap-reverse
其实是镜像的,你只要记得 wrap
是怎么换行,那就知道 wrap-reverse
是怎么换行的。
2.4 flex-flow
flex-flow
是 flex-direction
和 flex-wrap
属性的简写,默认值是 row nowrap
。
.container { flex-flow: column wrap; }
2.5 justify-content
justify-content
定义了主轴上子元素的对齐方式。
.container { justify-content: flex-start | flex-end | center | space-between | space-around | space-evenly | start | end | left | right ... + safe | unsafe; /* Positional alignment */ justify-content: center; /* 居中排列 */ justify-content: start; /* Pack items from the start */ justify-content: end; /* Pack items from the end */ justify-content: flex-start; /* 从行首起始位置开始排列 */ justify-content: flex-end; /* 从行尾位置开始排列 */ justify-content: left; /* Pack items from the left */ justify-content: right; /* Pack items from the right */ /* Baseline alignment */ justify-content: baseline; justify-content: first baseline; justify-content: last baseline; /* Distributed alignment */ justify-content: space-between; /* 均匀排列每个元素 首个元素放置于起点,末尾元素放置于终点 */ justify-content: space-around; /* 均匀排列每个元素 每个元素周围分配相同的空间 */ justify-content: space-evenly; /* 均匀排列每个元素 每个元素之间的间隔相等 */ justify-content: stretch; /* 均匀排列每个元素 'auto'-sized 的元素会被拉伸以适应容器的大小 */ /* Overflow alignment */ justify-content: safe center; justify-content: unsafe center; /* Global values */ justify-content: inherit; justify-content: initial; justify-content: unset; }
flex-start
(默认):从行首开始排列。每行第一个弹性元素与行首对齐,同时所有后续的弹性元素与前一个对齐。flex-end
:从行尾开始排列。每行最后一个弹性元素与行尾对齐,其他元素将与后一个对齐。start
:从行首开始排列。每行第一个元素与行首对齐,同时所有后续的元素与前一个对齐。end
: 从行尾开始排列。每行第一个元素与行尾对齐,同时所有后续的元素与前一个对齐。left
:伸缩元素一个挨一个在对齐容器得左边缘,如果属性的轴与内联轴不平行,则left
的行为类似于start
。right
:元素以容器右边缘为基准,一个挨着一个对齐,如果属性轴与内联轴不平行,则right
的行为类似于end
。center
:伸缩元素向每行中点排列。每行第一个元素到行首的距离将与每行最后一个元素到行尾的距离相同。space-between
:在每行上均匀分配弹性元素。相邻元素间距离相同。每行第一个元素与行首对齐,每行最后一个元素与行尾对齐。space-around
:在每行上均匀分配弹性元素。相邻元素间距离相同。每行第一个元素到行首的距离和每行最后一个元素到行尾的距离将会是相邻元素之间距离的一半。。space-evenly
:flex 项都沿着主轴均匀分布在指定的对齐容器中。相邻 flex 项之间的间距,主轴起始位置到第一个 flex 项的间距,主轴结束位置到最后一个 flex 项的间距,都完全一样。baseline
/first baseline
/last baseline
:指定参与第一或最后基线对齐:将盒子的第一或最后基线集的对齐基线与它的基线共享组中所有盒子的第一或最后基线集中的相应基线对齐。第一条基线的回退对齐是开始,最后一条基线的回退对齐是结束。stretch
:如果项目的总和尺寸小于对齐容器的尺寸,任何自动尺寸的项目都会被平均增加(而不是按比例增加),同时仍然受到max-height
/max-width
(或同等功能)所施加的限制,这样总和尺寸就会沿着主轴完全充满对齐容器。safe
:与对齐关键字一起使用,如果选定的关键字会导致元素溢出容器造成数据丢失,那么将会使用start
代替它。unsafe
:无论项目和对齐容器的相对大小如何,给定的对齐值都会得到遵守。
请注意,主流浏览器对这些值的支持还不是那么完善的。例如,space-between
从未得到某些版本的 Edge 的支持。MDN有详细的图表。最安全的值是flex-start
、flex-end
和center
。
还有两个额外的关键字可以与这些值配对:safe
和unsafe
。使用safe
可确保无论您如何进行此类定位,都不能将元素推送到屏幕外(例如,从顶部),从而使内容无法滚动(称为“数据丢失”) .
2.6 align-items
align-items
定义了交叉轴上的子元素的对齐方式。
.container { align-items: stretch | flex-start | flex-end | center | baseline | first baseline | last baseline | start | end | self-start | self-end + ... safe | unsafe; /* Basic keywords */ align-items: normal; align-items: stretch; /* Positional alignment */ align-items: center; /* Pack items around the center */ align-items: start; /* Pack items from the start */ align-items: end; /* Pack items from the end */ align-items: flex-start; /* Pack flex items from the start */ align-items: flex-end; /* Pack flex items from the end */ align-items: self-start; align-items: self-end; /* Baseline alignment */ align-items: baseline; align-items: first baseline; align-items: last baseline; /* Overflow alignment (for positional alignment only) */ align-items: safe center; align-items: unsafe center; /* Global values */ align-items: inherit; align-items: initial; align-items: unset; }
normal
:这个关键字的效果取决于我们处在什么布局模式中:
- 在绝对定位的布局中,对于被替代的绝对定位盒子,这个效果和
start?
的效果的一样;对于其他所有绝对定位的盒子,这个效果和stretch
的效果一样。 - 在绝对定位布局的静态位置上,效果和
stretch
一样。 - 对于那些弹性项目而言,效果和
stretch
一样。 - 对于那些网格项目而言,效果和
stretch
一样,除了有部分比例或者一个固定大小的盒子的效果像start
。 - 这个属性不适用于块级盒子和表格。
stretch
(默认):弹性项包含外边距的交叉轴尺寸被拉升至行高flex-start / start / self-start
:元素向侧轴起点对齐。flex-end / end / self-end
:元素向侧轴终点对齐。center
:元素在侧轴居中。如果元素在侧轴上的高度高于其容器,那么在两个方向上溢出距离相同。baseline
/first baseline
/last baseline
:所有元素向基线对齐。侧轴起点到元素基线距离最大的元素将会于侧轴起点对齐以确定基线。
2.7 align-content
align-content
用来定义多根轴线的对齐方式,可以取值与justify-content
相同,但是只在有多根轴线时生效。
注意: 该属性只对多行
flex
容器有效,其中flex-wrap
设置为 或wrap
)wrap-reverse
。单行flex
容器(即flex-wrap
设置为其默认值no-wrap
)不会存在align-content
。
.container { align-content: flex-start | flex-end | center | space-between | space-around | space-evenly | stretch | start | end | baseline | first baseline | last baseline + ... safe | unsafe; /* 基本位置对齐 */ /*align-content 不采用左右值 */ align-content: center; /* 将项目放置在中点 */ align-content: start; /* 最先放置项目 */ align-content: end; /* 最后放置项目 */ align-content: flex-start; /* 从起始点开始放置 flex 元素 */ align-content: flex-end; /* 从终止点开始放置 flex 元素 */ /* 默认对齐 */ align-content: normal; /*基线对齐*/ align-content: baseline; align-content: first baseline; align-content: last baseline; /* 分布式对齐 */ align-content: space-between; /* 均匀分布项目 第一项与起始点齐平, 最后一项与终止点齐平 */ align-content: space-around; /* 均匀分布项目 项目在两端有一半大小的空间*/ align-content: space-evenly; /* 均匀分布项目 项目周围有相等的空间 */ align-content: stretch; /* 均匀分布项目 拉伸‘自动’ - 大小的项目以充满容器 */ /* 溢出对齐 */ align-content: safe center; align-content: unsafe center; /* 全局属性 */ align-content: inherit; /* 继承 */ align-content: initial; /* 初始值 */ align-content: unset; /* 未设置 */ }
normal
(默认):这些项按默认位置填充,就像没有设置对齐内容值一样。flex-start
: 所有行从垂直轴起点开始填充。第一行的垂直轴起点边和容器的垂直轴起点边对齐。接下来的每一行紧跟前一行。flex-end
: 所有行从垂直轴末尾开始填充。最后一行的垂直轴终点和容器的垂直轴终点对齐。同时所有后续行与前一个对齐。start
: 所有行从容器的起始边缘开始填充。end
: 所有行从容器的结束边缘开始填充。baseline
/first baseline
/last baseline
:指定参与第一或最后基线对齐:将盒子的第一或最后基线集的对齐基线与它的基线共享组中所有盒子的第一或最后基线集中的相应基线对齐。第一条基线的回退对齐是开始,最后一条基线的回退对齐是结束。center
:所有行朝向容器的中心填充。每行互相紧挨,相对于容器居中对齐。容器的垂直轴起点边和第一行的距离相等于容器的垂直轴终点边和最后一行的距离。space-between
:所有行在容器中平均分布。相邻两行间距相等。容器的垂直轴起点边和终点边分别与第一行和最后一行的边对齐。space-around
:所有行在容器中平均分布,相邻两行间距相等。容器的垂直轴起点边和终点边分别与第一行和最后一行的距离是相邻两行间距的一半。space-evenly
:所有行沿垂直轴均匀分布在对齐容器内。每对相邻的项之间的间距,主开始边和第一项,以及主结束边和最后一项,都是完全相同的。stretch
: 拉伸所有行来填满剩余空间。剩余空间平均地分配给每一行。safe
:与对齐关键字一起使用。如果所选的关键字意味着项溢出对齐容器(data loss
),则将采用备用策略对项进行对齐,就像启动了start
对齐模式一样。unsafe
:与对齐关键字一起使用。无论元素和对齐容器的相对大小如何、是否会导致一些元素溢出可见范围(data loss
),都使用给定的对齐值。
<ul class="flex-container flex-start"> <li class="flex-item">1</li> <li class="flex-item">2</li> <li class="flex-item">3</li> <li class="flex-item">4</li> <li class="flex-item">5</li> <li class="flex-item">6</li> </ul> <ul class="flex-container flex-end"> <li class="flex-item">1</li> <li class="flex-item">2</li> <li class="flex-item">3</li> <li class="flex-item">4</li> <li class="flex-item">5</li> <li class="flex-item">6</li> </ul> <ul class="flex-container center"> <li class="flex-item">1</li> <li class="flex-item">2</li> <li class="flex-item">3</li> <li class="flex-item">4</li> <li class="flex-item">5</li> <li class="flex-item">6</li> </ul> <ul class="flex-container space-between"> <li class="flex-item">1</li> <li class="flex-item">2</li> <li class="flex-item">3</li> <li class="flex-item">4</li> <li class="flex-item">5</li> <li class="flex-item">6</li> </ul> <ul class="flex-container space-around"> <li class="flex-item">1</li> <li class="flex-item">2</li> <li class="flex-item">3</li> <li class="flex-item">4</li> <li class="flex-item">5</li> <li class="flex-item">6</li> </ul> <ul class="flex-container stretch"> <li class="flex-item">1</li> <li class="flex-item">2</li> <li class="flex-item">3</li> <li class="flex-item">4</li> <li class="flex-item">5</li> <li class="flex-item">6</li> </ul>