Skip to content

flex布局

Flexbox (弹性盒子)布局是在 2017 年 10 月的 W3C 候选建议添加的一种布局方式,旨在提供一种更有效的方式来在容器与元素之间布局、对齐、分配空间,即使元素的大小未知、甚至是动态生成。

弹性盒子布局背后的主要思想是使容器能够改变其元素的宽度、高度(和顺序),以便更好的填充可用空间(主要是为了适应所有的显示设备与屏幕尺寸)。

更重要的是,与常规布局(垂直布局与水平布局)相反,弹性盒子布局与方向无关,虽然这些技术适用于页面,但是对于支撑大型复杂的页面来说它们缺乏灵活性(特别是在布局方向更改、调整大小、拉伸、缩小等方面)。

基础知识和术语

由于 flexbox 是一个完整的模块,而不是一个单一的属性,它涉及很多事情,包括它的整套属性。其中一些应该在容器(父元素,称为“flex 容器”)上设置,而其他的则应该在子元素(称为“flex items”)上设置。

如果“常规”布局同时基于块流和内联流方向,则挠性布局基于“柔性流方向”。请从规范中查看此图,解释 flex 布局背后的主要思想。

项目将按照 main axis(主轴、十字轴)从左(main-star)到右(main-end)进行布局,或者是按照 cross axis(交叉轴)从上(cross-start)到下(cross-end)布局

注意

flexbox 没有横轴与竖轴的概念,因为主轴与交叉轴是可以变化的。

  • main axis(主轴):flexbox 的主轴是项目的布局核心。它不一定是水平的,主要取决于 flex-direction 属性(见下文)
  • main-start | main-end:弹性项目放置在容器内,从开始到结束的位置。
  • main size:弹性项的宽度或高度(以主维度中的为准)是项目的主要尺寸。弹性项的主尺寸属性是“宽度”或“高度”属性,以主维度中的个体为准。
  • cross axis:垂直于主轴的轴称为交叉轴。它的方向取决于主轴方向。
  • cross-start | cross-end:弹性项目放置在容器内,从开始到结束的位置。
  • cross size:弹性项的宽度或高度(以十字尺寸中的较大者为准)是项的交叉大小。交叉大小属性是交叉维度中的“宽度”或“高度”中的任何一个。

父项常见属性

想要使用 flexbox 布局,首先需要开启 flex 布局模式

css
.container {
  display: flex; /* or inline-flex */
}

flex-direction 主轴方向

使用 flex-direction 属性可以设置主轴,从而确定 flex 子元素的放置方向。flexbox 是单向布局概念,将 flexbox 中的内容在水平列或者垂直列进行布局

css
.container {
  flex-direction: row | row-reverse | column | column-reverse;
}
  • row(默认值):从左到右是 ltr,从右到左是 rtl。
  • row-reverse:从右到左是 ltr,从左到右是 rtl。
  • column:与上面相同,但是 row 变为从上到下
  • column-reverse:与相同 row-reverse ,但从下到上

1、row(默认)

默认方向是行。这意味着主轴是水平的,而横轴是垂直的。这也意味着主轴从左侧开始,而横轴从顶部开始。

css
.flex-container {
  display: flex;
  flex-direction: row;
}
1
2
3

2、row-reverse

与 row 类似,我们有 row-reverse。该方向不会交换主轴/交叉轴,但会交换主轴开始的位置。主轴现在从右边开始,而横轴没有改变,仍然从顶部开始。

css
.flex-container {
  display: flex;
  flex-direction: row-reverse;
}
1
2
3

3、column

列方向完全交换了我们的轴,所以现在主轴是垂直的,横轴是水平的。

css
.flex-container {
  display: flex;
  flex-direction: column;
}
1
2
3

4、column-reverse

column-reverse 方向与 column 基本相同,但它反转了主轴的方向,因此现在项目从容器的底部开始。

css
.flex-container {
  display: flex;
  flex-direction: column-reverse;
}
1
2
3

flex-wrap

默认情况下,弹性项目将全部尝试适合一行。您可以更改此设置,并允许使用此属性根据需要包装项。

css
.container {
  flex-wrap: nowrap | wrap | wrap-reverse;
}
  • nowrap (默认值):所有子元素都将在一行上

    1
    2
    3
    4
    5
    6
    7
    8
  • wrap :子元素将从上到下换行到多行。

    1
    2
    3
    4
    5
    6
    7
    8
  • wrap-reverse :子元素将从下到上换行到多行。

    1
    2
    3
    4
    5
    6
    7
    8

justify-content 对齐方式

这个属性定义了子元素沿主轴的对齐方式。当一行上所有的子元素都不没有占满整个空间时,有助于分配额外的剩余空间。如果子元素已经占满父元素的宽度并溢出到下一行,可以对子元素的对齐方式进行控制

css
.container {
  justify-content: flex-start | flex-end | center | space-between | space-around | space-evenly | start | end | left | right ... + safe | unsafe;
}
  • flex-start(默认值):将元素从主轴的开始处进行布局。
  • flex-end:将元素从主轴的末尾处进行布局。
  • center:子元素居中显示
  • space-between: 均分分布在一行,第一项从最左边开始,最后一项贴齐右边。
  • space-around:均匀分布在一行中,每个子元素左右两边的间距相等。
  • space-evenly: 每个子元素直接的距离相等。

justify-content 演示代码

对于下方所有示例,我们将假设 flex-items 的宽度为 20%。

html
<!doctype html>
<html lang="zh-CN">
  <head>
    <meta charset="UTF-8" />
    <title>flex-direction</title>
    <style>
      .flex-container {
        display: flex;
        border: 1px dashed black;
        justify-content: flex-start;
      }

      .flex-item {
        width: 20%;
        height: 10rem;
        background-color: deepskyblue;
        border: 1px solid black;
      }
    </style>
  </head>
  <body>
    <div class="flex-container">
      <div class="flex-item">1</div>
      <div class="flex-item">2</div>
      <div class="flex-item">3</div>
    </div>
  </body>
</html>
  • 1、flex-start(默认)

    将所有项目放置在主轴的起点,默认情况下是轴的左侧。这也是 justify-content 的默认行为。

    css
    .flex-container {
      display: flex;
      justify-content: flex-start;
    }
    1
    2
    3
  • 2、flex-end

    将所有项目放置在主轴的末端,默认情况下是轴的右侧。

    css
    .flex-container {
      display: flex;
      justify-content: flex-end;
    }
    1
    2
    3
  • 3、center

    将所有项目放置在主轴的中心。这是在 CSS 中居中元素的最简单方法之一。

    css
    .flex-container {
      display: flex;
      justify-content: center;
    }
    1
    2
    3
  • 4、space-between

    这会占用容器内的所有额外空间,并将其均匀分布在每个元素之间,以在填充整个容器的同时将它们彼此间隔得尽可能远。

    css
    .flex-container {
      display: flex;
      justify-content: space-between;
    }
    1
    2
    3
  • 5、space-around

    这与 space-between 非常相似,但它也在容器外部和第一个/最后一个元素之间增加了空间。容器外部和第一个/最后一个元素之间的空间量正好是元素之间空间量的一半。

    css
    .flex-container {
      display: flex;
      justify-content: space-around;
    }
    1
    2
    3

总结

属性名效果
flex-start默认值从头部开始如果主轴是 x 轴,则从左到右
flex-end从尾部开始排列
center在主轴居中对齐(如果主轴是 x 轴则水平居中)
space-around平分剩余空间
space-between先两边贴边再平分剩余空间(重要)

align-items 子元素项

align-items 这定义了弹性项目沿当前行的交叉轴布局方式的默认行为。将其 justify-content 视为十字轴(垂直于主轴)的版本。

该属性是控制子项在侧轴(默认是 y 轴)上的排列方式 在子项为单项(单行)的时候使用

css
.container {
  align-items: stretch | flex-start | flex-end | center | baseline | first baseline | last baseline | start | end | self-start | self-end + ... safe | unsafe;
}
  • stretch(默认值):拉伸以填充容器(仍遵循最小宽度/最大宽度)
  • flex-start / start / self-start:项目放置在十字轴的开头。这些之间的区别是微妙的。
  • flex-end / end / self-end:末端对齐
  • center:在十字轴上居中
  • baseline :项目对齐,例如其基线对齐

对于下方这些示例,我们将假设 flex-items 的宽度均为 20%,但元素的高度都不同。

html
<style>
    .flex-container {display: flex;border: 1px dashed black;}
    .flex-container .item {width: 100px;background-color: deepskyblue;border: 1px solid;}
    .flex-container .item:nth-child(0) {height: 60px;}
    .flex-container .item:nth-child(1) {height: 80px;}
    .flex-container .item:nth-child(2) {height: 100px;}
</style>

<div class="flex-container">
    <div class="item">1</div>
    <div class="item">2</div>
    <div class="item">3</div>
</div>

image-20211208232130028

  • 1、flex-start

    这与 justify-content 的 flex-start 的工作原理相同,但默认情况下将从交叉轴的顶部开始。

    css
    .flex-container {
      display: flex;
      align-items: flex-start;
    }
    1
    2
    3
  • 2、flex-end

    这与 justify-content 的 flex-end 的工作原理相同,但默认情况下将从交叉轴的底部开始。

    css
    .flex-container {
      display: flex;
      align-items: flex-end;
    }
    1
    2
    3
  • 3、center

    这与 justify-content 的 center相同,但将基于交叉轴居中。

    css
    .flex-container {
      display: flex;
      align-items: center;
    }
    1
    2
    3
  • 4、stretch(默认)

    css
    .flex-container {
      display: flex;
      align-items: stretch;
    }
    1
    2
    3
属性名效果
flex-start默认值从头部开始如果主轴是 x 轴,则从左到右
flex-end从尾部开始排列
center在主轴居中对齐(如果主轴是 x 轴则水平居中)
stretch拉伸

高级 Flexbox 属性

目前分享的内容已经涵盖了 flexbox 的所有基础和进阶属性,现在我想涵盖一些高级/小众的 flexbox 属性。

添加间隙

到目前为止我们还没有涉及的一件事是能够在 flexbox 容器中的元素之间添加间隙。你可以尝试使用margin/padding来执行此操作,但更简单的方法是使用 gap 属性。此属性将根据我们传递给 gap 的值在每个项目之间添加空间。

css
.container {
  display: flex;
  ...
  gap: 10px;
  gap: 10px 20px; /* row-gap column gap */
  row-gap: 10px;
  column-gap: 20px;
}
1
2
3
4
5

正如你所看到的,我们上面的每个项目之间都有 10px 的间隙。这种差距也适用于多行 flex 容器。

附录

  1. flexbox 完全入门指引手册: https://css-tricks.com/snippets/css/a-guide-to-flexbox/
  2. flex 小游戏:https://flexboxfroggy.com/