写给自己看的display: flex布局教程
source link: https://www.zhangxinxu.com/wordpress/2018/10/display-flex-css3-css/?amp%3Butm_medium=referral
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
byzhangxinxu from https://www.zhangxinxu.com/wordpress/?p=8063
本文可全文转载,但需得到原作者书面许可,同时保留原作者和出处,摘要引流则随意。
//zxx: 本教程所有布局效果(含交互)为实时渲染,若布局异常,可以点击这里访问原文。
一、前言&索引
给div这类块状元素元素设置 display:flex
或者给span这类内联元素设置 display:inline-flex
,flex布局即创建!其中,直接设置 display:flex
或者 display:inline-flex
的元素称为flex容器,里面的子元素称为flex子项。
而Flex布局相关属性正好分为两拨,一拨作用在flex容器上,还有一拨作用在flex子项上。具体参见下表,点击可快速索引。
作用在flex容器上 作用在flex子项上无论作用在flex容器上,还是作用在flex子项,都是控制的flex子项的呈现,只是前者控制的是整体,后者控制的是个体。
其他说明:
-
本教程所有案例HTML结构为:
container(flex容器) div(flex子项) > img div(flex子项) > img div(flex子项) > img
同时,为了便于区分,flex容器区域使用虚框标示,flex子项增加了白蓝径向渐变背景色,图片上显示了原始序号。
- Flex布局中还有主轴和交叉轴的概念,为避免过多概念干扰,本教程省略相关措辞,而是使用水平方向和垂直方向代替 ①
。
//zxx: ① writing-mode属性可以改变文档流方向,此时主轴是垂直方向,但实际开发很少遇到这样场景,因此,初学的时候,直接使用水平方向和垂直方向理解不会有任何问题,反而易于理解。
二、作用在flex容器上的CSS属性
1. flex-direction
flex-direction
用来控制子项整体布局方向,是从左往右还是从右往左,是从上往下还是从下往上。和CSS的direction属性相比就是多了个 flex
。
语法如下:
flex-direction: row | row-reverse | column | column-reverse;
其中:
row 默认值,显示为行。方向为当前文档水平流方向,默认情况下是从左往右。如果当前水平文档流方向是rtl
(如设置
direction:rtl
),则从右往左。
row-reverse
显示为行。但方向和
row
属性值是反的。
column
显示为列。
column-reverse
显示为列。但方向和
column
属性值是反的。
眼见为实,点击下面对应单选项,可以看到实时的布局效果:
2. flex-wrap
flex-wrap
用来控制子项整体单行显示还是换行显示,如果换行,则下面一行是否反方向显示。这个属性比较好记忆,在CSS世界中,只要看到单词wrap一定是与换行显示相关的, word-wrap
属性或者 white-space:nowrap
或者 pre-wrap
之类。
语法如下:
flex-wrap: nowrap | wrap | wrap-reverse;
其中:
nowrap- flex子项最小内容宽度
min-content
之和大于flex容器宽度,则内容溢出,表现和white-space:nowrap
类似。 - 如果flex子项最小内容宽度
min-content
之和小于flex容器宽度,则:- flex子项默认的
fit-content
宽度之和大于flex容器宽度,则flex子项宽度收缩,正好填满flex容器,内容不溢出。 - flex子项默认的
fit-content
宽度之和小于flex容器宽度,则flex子项以fit-content
宽度正常显示,内容不溢出。
- flex子项默认的
在下面案例中,示意的图片默认有设置 max-width:100%
,flex子项div没有设置宽度,因此,flex子项最小宽度是无限小,表现为图片宽度收缩显示。如果我们取消 max-width:100%
样式,则此时flex子项最小宽度就是图片宽度,就可以看到图片溢出到了flex容器之外。
眼见为实,点击下面对应单复选框,可以看到实时的布局效果:
img{max-width:100%;}
3. flex-flow
flex-flow
属性是 flex-direction
和 flex-wrap
的缩写,表示flex布局的flow流动特性,语法如下:
flex-flow: <‘flex-direction’> || <‘flex-wrap’>
当多属性同时使用的时候,使用空格分隔。
举个例子,容器元素如下设置:
.container { display: flex; flex-flow: row-reverse wrap-reverse; }
实时效果如下:
可以看到水平排序从右往左( row-reverse
属性值的作用),以及换行的那一行在上面( wrap-reverse
属性值的作用)。
4. justify-content
justify-content
属性决定了水平方向子项的对齐和分布方式。CSS text-align
有个属性值为 justify
,可实现两端对齐,所以,当我们想要控制flex元素的水平对齐方式的时候,记住 justify
这个单词, justify-content
属性也就记住了。
justify-content
可以看成是 text-align
的远房亲戚,不过前者控制flex元素的水平对齐外加分布,后者控制内联元素的水平对齐。
语法如下:
justify-content: flex-start | flex-end | center | space-between | space-around | space-evenly;
其中:
flex-start 默认值。逻辑CSS属性值,与文档流方向相关。默认表现为左对齐。 flex-end 逻辑CSS属性值,与文档流方向相关。默认表现为右对齐。 center 表现为居中对齐。 space-between
眼见为实,点击下面对应单复选框,可以看到实时的布局效果:
direction:rtl(测试flex-start/flex-end)
5. align-items
align-items
中的 items
指的就是flex子项们,因此 align-items
指的就是flex子项们相对于flex容器在垂直方向上的对齐方式,大家是一起顶部对齐呢,底部对齐呢,还是拉伸对齐呢,类似这样。
语法如下:
align-items: stretch | flex-start | flex-end | center | baseline;
其中:
stretch 默认值。flex子项拉伸。在演示中我们可以看到白蓝径向渐变背景区域是上下贯穿flex容器的,就是因为flex子项的高度拉伸到容器高度导致。如果flex子项设置了高度,则按照设置的高度值渲染,而非拉伸。 flex-start 逻辑CSS属性值,与文档流方向相关。默认表现为容器顶部对齐。 flex-end 逻辑CSS属性值,与文档流方向相关。默认表现为容器底部对齐。 center 表现为垂直居中对齐。 baseline 表现为所有flex子项都相对于flex容器的基线(字母x的下边缘)对齐。眼见为实,点击下面对应单选框,可以看到实时的布局效果:
6. align-content
align-content
可以看成和 justify-content
是相似且对立的属性, justify-content
指明水平方向flex子项的对齐和分布方式,而 align-content
则是指明垂直方向每一行flex元素的对齐和分布方式。如果所有flex子项只有一行,则 align-content
属性是没有任何效果的。
语法如下:
align-content: stretch | flex-start | flex-end | center | space-between | space-around | space-evenly;
其中:
stretch 默认值。每一行flex子元素都等比例拉伸。例如,如果共两行flex子元素,则每一行拉伸高度是50%。 flex-start 逻辑CSS属性值,与文档流方向相关。默认表现为顶部堆砌。 flex-end 逻辑CSS属性值,与文档流方向相关。默认表现为底部堆放。 center 表现为整体垂直居中对齐。 space-between 表现为上下两行两端对齐。剩下每一行元素等分剩余空间。 space-around 每一行元素上下都享有独立不重叠的空白空间。 space-evenly 每一行元素都完全上下等分。眼见为实,我们给flex容器设置高度500像素,然后点击下面对应单选框,可以看到实时的布局效果:
三、作用在flex子项上的CSS属性
1. order
我们可以通过设置 order
改变某一个flex子项的排序位置。
语法:
order: <integer>; /* 整数值,默认值是 0 */
所有flex子项的默认 order
属性值是0,因此,如果我们想要某一个flex子项在最前面显示,可以设置比0小的整数,如 -1
就可以了。
眼见为实,下面flex容器有3个子元素,现在,我们给第2个子元素设置 order
属性值,看看其排列位置有何变化。点击下面的单选框,可以看到实时的交互效果:
2. flex-grow
flex-grow
属性中的grow是扩展的意思,扩展的就是flex子项所占据的宽度,扩展所侵占的空间就是除去元素外的剩余的空白间隙。
具体的扩展比较复杂。在展开之前,我们先看下语法。
语法:
flex-grow: <number>; /* 数值,可以是小数,默认值是 0 */
flex-grow
不支持负值,默认值是0,表示不占用剩余的空白间隙扩展自己的宽度。如果 flex-grow
大于0,则flex容器剩余空间的分配就会发生,具体规则如下:
- 所有剩余空间总量是1。
- 如果只有一个flex子项设置了
flex-grow
属性值:
flex-grow flex-grow
具体可参见下面“grow案例1”。
- 如果有多个flex设置了
flex-grow
属性值:
- 如果
flex-grow
值总和小于1,则每个子项扩展的空间就总剩余空间和当前元素设置的flex-grow
比例的计算值。 - 如果
flex-grow
值总和大于1,则所有剩余空间被利用,分配比例就是flex-grow
属性值的比例。例如所有的flex子项都设置flex-grow:1
,则表示剩余空白间隙大家等分,如果设置的flex-grow
比例是1:2:1,则中间的flex子项占据一半的空白间隙,剩下的前后两个元素等分。
具体可参见下面“grow案例2”。
- 如果
grow案例1:
flex容器有3个子元素,现在,我们仅给第2个子元素设置 flex-grow
属性值,看看其占据尺寸有何变化。点击下面的单选框,可以看到实时的交互效果:
此实例演示中,仅一个flex子项设置了 flex-grow
属性值,当我们选择 0.5
的时候,值小于1,剩余空间用不完,因此,扩展的宽度是总剩余宽度是0.5,也就是一半;当我们选择 1
的时候,正好所有空间都使用;当我们选择 2
的时候,效果一样,因为没有其他参与分配的子项,因此渲染表现和 1
一样。
grow案例2:
flex容器有3个子元素,默认所有子项都设置了 flex-grow:0.25
,现在我们点击下面的单选框,改变第2个子元素的 flex-grow
属性值,看看其占据尺寸有何变化:
此实例演示中,因为3个子项都是0.25,因此默认还剩余25%的剩余空间;如果我们选择 flex-grow:0
,则加起来的 flex-grow
是 0.5
,因此剩余50%空间;如果我们选择 flex-grow:0.5
,则加起来的 flex-grow
是 1
,因此没有剩余空间,同时空间占用比例为1:2:1,最终效果符合此预期;如果我们选择 flex-grow:1
,则加起来的 flex-grow
大于 1
,剩余空间按比例分配,为1:4:1,最终效果也确实如此。
以上就是 flex-grow
属性的作用规则。
3. flex-shrink
shrink是“收缩”的意思, flex-shrink
主要处理当flex容器空间不足时候,单个元素的收缩比例。
语法如下:
flex-shrink: <number>; /* 数值,默认值是 1 */
flex-shrink
不支持负值,默认值是1,也就是默认所有的flex子项都会收缩。如果设置为0,则表示不收缩,保持原始的 fit-content
宽度。
flex-shrink
的内核跟 flex-grow
很神似, flex-grow
是空间足够时候如何利用空间, flex-shrink
则是空间不足时候如何收缩腾出空间。总有点CP的味道。
两者的规则也是类似。已知flex子项不换行,且容器空间不足,不足的空间就是“完全收缩的尺寸”:
- 如果只有一个flex子项设置了
flex-shrink
:flex-shrink flex-shrink
- 如果多个flex子项设置了
flex-shrink
:-
flex-shrink
值的总和小于1,则收缩的尺寸不完全,每个元素收缩尺寸占“完全收缩的尺寸”的比例就是设置的flex-shrink
的值。 -
flex-shrink
值的总和大于1,则收缩完全,每个元素收缩尺寸的比例和flex-shrink
值的比例一样。下面案例演示的就是此场景。
-
眼见为实,flex容器有4个子元素,现在,我们给第2个子元素设置不同的 flex-shrink
属性值,看看其占据尺寸有何变化。点击下面的单选框,可以看到实时的交互效果:
此实例演示中,因为4个子项都是1,和远大于1,因此,完全收缩,不会有内容溢出。如果我们选择 flex-shrink:0
,则第2个flex子项不收缩,剩下3个flex子项等比例收缩;如果我们选择 flex-grow:1
,则4个子项1:1:1:1收缩;如果我们选择 flex-grow:2
,则完全收缩尺寸比例分配为1:2:1:1,第2个flex子项收缩的宽度最大,是其他元素的2倍。
以上就是 flex-shrink
属性的作用规则。
4. flex-basis
flex-basis
定义了在分配剩余空间之前元素的默认大小。相当于对浏览器提前告知:浏览器兄,我要占据这么大的空间,提前帮我预留好。
语法如下:
flex-basis: <length> | auto; /* 默认值是 auto */
默认值是 auto
,就是自动。有设置 width
则占据空间就是 width
,没有设置就按内容宽度来。
如果同时设置 width
和 flex-basis
,就渲染表现来看,会忽略 width
。flex顾名思义就是弹性的意思,因此,实际上不建议对flex子项使用 width
属性,因为不够弹性。
当剩余空间不足的时候,flex子项的实际宽度并通常不是设置的 flex-basis
尺寸,因为flex布局剩余空间不足的时候默认会收缩。
实例一则:
flex容器有3个子元素,现在,我们给第2个子元素设置不同的 flex-basis
属性值,看看其占据尺寸有何变化。点击下面的单选框,可以看到实时的交互效果:
选择最后一个 flex-basis:256px
会发现flex子项的宽度并不是 256px
,这是因为此时剩余空间不足,3个子项1:1:1收缩的缘故。
5. flex
flex
属性是 flex-grow
, flex-shrink
和 flex-basis
的缩写。
语法:
flex: none | auto | [ <'flex-grow'> <'flex-shrink'>? || <'flex-basis'> ]
其中第2和第3个参数( flex-shrink
和 flex-basis
)是可选的。默认值为 0 1 auto
。
案例演示:
第2个flex子项设置 flex:none
或者 flex:auto
,我们看看实时布局效果会有怎样的变化:
隐藏部分图片使空间剩余(为了测flex-grow)
此时第2个flex子项的 flex-grow
, flex-shrink
和 flex-basis
属性值分别是 0
, 1
,和 auto
。
经过上面一番测试,我们可以得到如下结论:
-
flex
默认值等同于flex:0 1 auto
; -
flex:none
等同于flex:0 0 auto
; -
flex:auto
等同于flex:1 1 auto
;
6. align-self
align-self
指控制单独某一个flex子项的垂直对齐方式,写在flex容器上的这个 align-items
属性,后面是items,有个s,表示子项们,是全体;这里是self,单独一个个体。其他区别不大,语法几乎一样:
align-self: auto | flex-start | flex-end | center | baseline | stretch;
唯一区别就是 align-self
多了个 auto
(默认值),表示继承自flex容器的 align-items
属性值。其他属性值含义一模一样,如下案例示意:
首先我们设置flex容器 baseline
对齐,然后点击下面的单选框,给第2个flex子项设置不同 align-self
属性值,观察其表现:
.container { display: flex; align-items: baseline; height: 240px; }
四、其他Flex知识点
- 在Flex布局中,flex子元素的设置
float
,clear
以及vertical-align
属性都是没有用的。 - Flexbox布局最适合应用程序的组件和小规模布局,而Grid布局则适用于更大规模的布局。
- 已经8102年了,Flex老语法不用在管了,舒爽弃之,然后私有前缀也不用再加了,看到就烦。
本教程优点在于交互效果可以实时体验,更直观。如果是转载文章,必定没有效果,访问原文即可。
说实话,自己之前Flex布局用得很少,本文内容自己也是边学边写,文中若有表述不准确的地方欢迎指正。
感谢阅读!
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK