CSS | Flex布局

Flex布局是CSS中常见的一种布局方式,不过笔者对于CSS不太擅长,所以写篇博客记录下自己学习flex布局的过程,下面就来简单讲解下flex布局的各项功能吧

启用flex

将容器元素的display属性设置为true即可启用flex布局

1
2
3
.container {
  display: flex;
}

对于行内元素,需要加上前缀inline

1
2
3
.inline-box {
  display: inline-flex;
}

对于webkit内核的浏览器(比如Safari),必须加上-webkit前缀。

1
2
3
4
.container {
  display: -webkit-flex; /* Safari */
  display: flex;
}

❕注意:设为 flex 布局以后,子元素的floatclearvertical-align属性将失效。

Flex Container

当将一个容器元素的display设置为flex后,该元素的所有子元素就变成了该元素的成员(item

下面依次介绍,容器元素中的常用属性,这些属性通常是用于给成员进行排布而使用的:

  • flex-direction
  • justify-content
  • align-items
  • flex-wrap
  • flex-flow
  • align-content

前置知识:主轴与交叉轴的概念

截图

容器默认存在两根轴:水平的主轴(main axis)和垂直的交叉轴(cross axis)。

flex-direction

CSS flex-direction 属性指定了内部元素是如何在 flex 容器中布局的,定义了主轴的方向 (正方向或反方向)。——MDN-flex-direction

该属性决定了items的排序方向,默认为row,代表横向

该属性接受以下的值:

  • row:flex 容器的主轴被定义为与文本方向相同。主轴起点和主轴终点与内容方向相同。(横向)
  • column: flex容器的主轴和块轴相同。主轴起点与主轴终点和书写模式的前后点相同。(直向)
  • row-reverse: 表现和row相同,但是置换了主轴起点和主轴终点。
  • column-reverse :表现和column相同,但是置换了主轴起点和主轴终点。

justify-content & align-items

  • justify-content是设定主轴的items排序方向
  • align-items是设定交叉轴的items排序方向

justify-content属性

justify-content属性定义了项目(items)在主轴上的对齐方式。

1
2
3
.box {
  justify-content: flex-start | flex-end | center | space-between | space-around;
}

它可能的取值有5个,具体对齐方式与轴的方向有关。下面假设主轴为从左到右

  • flex-start(默认值):左对齐
  • flex-end:右对齐
  • center: 居中
  • space-between:两端对齐,项目之间的间隔都相等。
  • space-around:每个项目两侧的间隔相等。所以,项目之间的间隔比项目与边框的间隔大一倍。

截图

align-items属性

align-items属性定义项目(items)在交叉轴上如何对齐。

它可能的取值有5个,具体的对齐方式与交叉轴的方向有关,下面假设交叉轴从上到下。

  • flex-start:交叉轴的起点对齐。
  • flex-end:交叉轴的终点对齐。
  • center:交叉轴的中点对齐。
  • baseline: 项目的第一行文字的基线对齐。
  • stretch(默认值):如果项目未设置高度或设为auto,将占满整个容器的高度。

截图

❕注意当你调转行或列的方向后,flex-start和flex-end对应的方向也被调转了。

比如原本页面上有这几个元素,如下图:

截图

对应的CSS与HTML如下:

CSS:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
.container {
  width: 600px;
  height: 400px;
  margin: 20px auto;
  display: flex;
  background-color: rgb(16, 113, 191);
  /* flex-direction: column;
  justify-content: center;
  align-items: center; */
}

.container .item{
  text-align: center;
  line-height: 100px;
  width: 100px;
  height: 100px;
  border: 1px solid white;
  border-radius: 5px;
  margin: 5px;
}

.container .green{
  background-color: rgb(61, 180, 71);
}

.container .yellow{
  background-color: rgb(213, 224, 92);
}

.container .red{
  background-color: rgb(200, 71, 71);
}

HTML:

1
2
3
4
5
<div class="container">
  <div class="item green">1</div>
  <div class="item yellow">2</div>
  <div class="item red">3</div>
</div>

现在给容器元素添加如下的代码

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
.container {
    width: 600px;
    height: 400px;
    margin: 20px auto;
    display: flex;
    background-color: rgb(16, 113, 191);
    /*新增代码*/
    flex-direction: column-reverse;
    justify-content: flex-start;
    align-items: flex-end; 
}
  • flex-direction: column-reverse使得元素从下向上排列,此时主轴变为从下至上,交叉轴变为从左至右
  • justify-content: flex-start使得元素以主轴的起点对其,此时元素向下方对齐
  • align-items: flex-end是的元素以交叉轴的终点对齐,此时元素向右靠拢

截图

flex-wrap

通过flex-wrap可以决定容器元素中的成员(item)是否可以分行。

可能取值:

  • nowrap(默认):不换行
  • wrap:换行
  • wrap-reverse:换行,第一行在下方。

如果将3个item多复制几分份,变成10个item,然后将它的宽度和高度加大一点,直至超过容器元素的宽度,这时候会发现item依旧在同一行,但是宽度被压缩了

截图

出现这种效果是因为flex-wrap的预设值是nowrap,意思是无论如何都只有一行

所以此时将其属性改为wrap,就可以实现换行了,效果如下:

截图

如果改为wrap-reverse就会变为下面的效果:

截图

flex-flow

flex-flowflex-direction与们flex-wrap组合起来的缩写,可以视情况分开写或者是组合写。

语法:

flex-flow: <flex-direction> || <flex-wrap>;

align-content

可以使用align-content来决定行与行之间隔多远,该属性的可能值如下:

  • flex-start: 多行都集中在顶部。
  • flex-end: 多行都集中在底部。
  • center: 多行居中。
  • space-between: 行与行之间保持相等距离。
  • space-around: 每行的周围保持相等距离。
  • stretch: 每一行都被拉伸以填满容器。

截图

小结

  • flex-direction决定成员(item)的排列方向,默认为row横向(左至右)
  • justify-content决定成员(item)在主轴上的对齐方式
  • align-items决定成员(item)在交叉轴上的对齐方式
  • flex-wrap决定成员在超过容器元素长度的时候是否要换行,默认为nowrap不换行
  • flex-flowflex-direction与们flex-wrap组合起来的缩写
  • align-content决定行与行之间的间隔多远

Flex Item

接下来介绍的是关于成员(item)元素可以使用的属性:

  • order
  • align-self
  • flex-basis
  • flex-grow
  • flex-shrink
  • flex

order

  • order属性定义item排列顺序
  • 数值越小,排列越靠前,默认为0

语法:

1
2
3
.item {
  order: <integer>;
}

截图

比如想要把刚才的红色成员(item)排在第一位,将该itemorder属性设置为负数即可,效果如下:

截图

align-self

用于覆盖容器元素align-items设定的,通过这个属性控制单个成员元素的对齐方式这个属性接受和align-items一样的值)。

默认值为auto表示继承父元素的align-items属性,如果没有父元素,则等同于stretch

语法:

1
2
3
.item {
  align-self: auto | flex-start | flex-end | center | baseline | stretch;
}

比如,将前面案例中的2成员元素的align-self设置为flex-end,效果如下图:

截图

flex-basis

CSS 属性 flex-basis 指定了成员(item)在主轴方向上的初始大小

语法:

1
2
3
.item {
  flex-basis: <length> | auto; /* default auto */
}
  • 默认值为auto即为元素原本的大小
  • 若不适用box-sizing属性改变盒模型,该属性决定内容(content)的尺寸
  • 当一个成员被同时设置了flex-basisauto以外的值)和width,此时flex-basis优先级更高
  • 如果此时在 flex-direction: column 情况下设置了height,此时flex-basis优先级更高

flex-grow

flex-grow是指当容器元素主轴方向有剩余空间的时候,成员(item沿着主轴方向扩大的设定

语法:

1
2
3
.item {
  flex-grow: <number>; /* default 0 */
}
  • 默认取值为0

来看下实际例子:

截图

在上图的情况下,给所有成员(item)加上flex-grow:1,然后3个box就分别扩大了一些,占满了主轴方向的空间。

它的原理是三个成员(item)的 flex-grow 都等于1的时候,这里的1是指占一份的意思,即是3个box各自占有剩余空间120px中的一份,这样每个成员(item)就向主轴方向扩大了40px(如下图)。

截图

现在尝试将2号成员(item)的flex-grow放大一些,比如将其flex-grow的值设置为3,其余两个成员的值不变,这样120px就会先分 为5份(1+3+1),2号成员(item)占其中3份,即对应的增大值为72px(3*(120/5))此时该元素的长度为132px(60+72)。

截图

如果将1号成员(item)的flex-grow设定为0则其成员保持原本的大小不变,其余成员按照3+1将120px分为4份,按照比例增长对应的长宽。

截图

flex-shrink

flex-shrink则与flex-frow相反,是指当成员(item主轴方向的大小总和超过容器元素的时候,成员(item沿主轴方向怎样缩小的设定

简单来说就是指定了成员(item)元素在当前主轴没有剩余空间的时候收缩规则可以理解为空间不够的时候该成员元素的缩小比例,数字越大缩小的越多。

语法:

1
2
3
.item {
  flex-shrink: <number>; /* default 1 */
}
  • 默认值为1
  • 负数对于该属性无效

来看下实际的例子:

截图

现在将flex-warp改为nowrap,然后回发现3个成员(item)会挤在同一行,但是宽度被缩小了,这是由于flex-shrink的预设值为1导致的。

比如3个成员(item)都是0的时候,代表当主轴方向空间不足时,都不能缩小对应的成员(item)元素

此时,3号元素就会突出在容器元素的外面, 如下图:

截图

现在将每个成员(item)元素加上flex-shrink:1的设定,意思是1、2、3三个成员各自分担被缩小的空间(90-90/3,即是每个成员(item)减去30px的宽度,此时每个元素的长度为60px

截图

若此时将2号成员(item)的flex-shrink设置为3,此时2号成员的宽度就会减去超出空间(90px)的3/5的大小,此时2号元素的长度变为36px(90-90*(3/5)),1号和3号元素的长度为72px(90-90*(1/5)

截图

如果将其flex-shrink设定为0,代表不做任何缩小

截图

flex

flex属性与容器元素的flex-flow属性类似,此属性为flex-growflex-shrink以及flex-basis组合起来的缩写。

语法:

1
2
3
.item {
  flex: none | [ <'flex-grow'> <'flex-shrink'>? || <'flex-basis'> ]
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
/* 一个值,无单位数字:flex-grow */
flex: 2;

/* 一个值,width/height: flex-basis */
flex: 10em;
flex: 30px;
flex: min-content;

/* 两个值:flex-grow | flex-basis */
flex: 1 30px;

/* 两个值:flex-grow | flex-shrink */
flex: 2 2;

/* 三个值:flex-grow | flex-shrink | flex-basis */
flex: 2 2 10%;
  • flex属性设置为 1 1 auto 的时候即flex-grow为1,flex-shrink为1以及flex-basisauto

    可以理解为:成员(item)元素会按照容器元素的宽度,平均分配空间去扩大或者缩小

    当容器元素有空间的时候同步扩大,当容器元素没有空间的时候同步缩小

  • 当将flex的值设置为0 1 150px

    可以理解为:该成员(item)元素的宽度最多是150px

    只会因为容器元素空间不足的时候而缩小,而不会因为容器元素有剩余空间的时候扩大

  • 当设置为0 0 200px的时候

    即该元素的大小就为200px,不能缩小也不能放大。

小结

  • order属性可以改变成员(item)元素的排列顺序
  • align-item可以改变单个成员(item)在交叉轴上的对齐方式
  • flex-grow是设定成员(item)元素的扩大比例,设定为0代表不扩大
  • flex-shrink是设定成员(item)元素的缩小比例,设定为0则不缩小
  • flex-basis是设定成员(item)元素主轴方向的基础大小
  • flexflex-grow, flex-shrinkflex-basis 组合起来的缩写

推荐练习网站

  • 通过青蛙小游戏的方式练习flex布局——链接

    截图

  • 通过塔防小游戏的方式练习flex布局——链接

    截图

  • 通过闯关小游戏的方式练习CSS——链接

    截图

参考文献