【CSS】flex布局

362 阅读6分钟

0. 简介

伸缩盒(Flexible box)能让普通容器(通常是块级元素)变为伸缩容器,使其有能力改变子元素的尺寸、顺序和对齐方式。

优点:

  • 当容器大小发生变化,子元素的大小会被自动调整,原先占据的空间会按比例缩放,以最优的方式填充可用空间。
  • 可以轻松解决移动端屏幕尺寸带来的布局问题,还能实现一些棘手的视觉效果,例如多列等高、垂直居中等

注意:伸缩容器的资源不能再使用float和vertical-align属性。

1. 主轴和侧轴

把某个容器元素变为伸缩容器时,这个容器就拥有了主轴和侧轴。主轴和侧轴是伸缩盒的核心概念,容器中资源的排列方式和对齐方式,都是参照这两根轴。

  • 主轴:默认从左到右
  • 侧轴:默认从上到下
<div class="flex">
    <section>1</section>
    <section>2</section>
    <section>3</section>
</div>

主轴和侧轴

1.1 flex-direction

flex-direction属性中的关键字 描述
row 将主轴定义为水平方向的轴,它是属性的默认值
row-reverse 创建的主轴与row相同,但子元素是从右往左排列
column 将主轴定义为垂直方向的轴
column-reverse 创建的主轴与column相同,但子元素是从下往上排列

flex-direction为row时:

flex-direction为row-reverse时:

flex-direction为column时:

flex-direction为column-reverse时:

1.2 flex-wrap

伸缩容器中的子元素默认只能排列一行中,如果子元素众多,那么会被自动压缩宽度。如果压到了最小,那么就会从容器中溢出。这点与浮动不同,浮动的元素如果超出了容器的宽度将被自动安排到下一行。

flex-wrap属性用于控制元素的换行,有三个关键字可选。

关键字 描述
nowrap 不允许子元素换行,它是属性的默认值
wrap 允许子元素换行
wrap-reverse 允许子元素换行,并且容器中的资源会从下到上排列

flex-wrap为nowrap时:

flex-wrap为wrap时:

flex-wrap为wrap-reverse时:

2. 对齐方式

  • 沿着主轴对齐的属性:justify-content
  • 沿着侧轴对齐的属性:align-items、align-self和align-content

2.1 align-items和align-self

  • align-items:用来控制容器中的所有子元素的对齐方式
  • align-self:只能控制一个子元素的对齐方式,除了align-items的几个关键字外还有一个auto(默认值)
align-items属性中的关键字 描述
flex-start 子元素仅靠在侧轴起点
flex-end 子元素仅靠在侧轴终点
center 子元素被安放在侧轴中部
baseline 根据子元素中的基线对齐
stretch 子元素会被拉伸,它是属性的默认值

效果图:

align-self属性被定义在子元素上,可选择的关键字有6个,除了上面5个之外,还多了一个auto,auto是属性的默认值,表示继承容器中的align-items的属性值。

<div class="flex" style="align-items:flex-start">
    <section>1</section>
    <section style="align-self:flex-end">2</section>
    <section style="align-self:center">3</section>
    <section>4</section>
    <section>5</section>
</div>

2.2 align-content

  • 用于侧轴对齐,但只在多行的时候才有效果。
  • 有6个关键字:flex-start、flex-end、center、stretch、space-between和space-around
  • align-content会把多行元素看为一个整体,然后整体对齐
  • space-between和space-around会让容器中的各行平均分布,space-around在每行的上下会留间隙,这两块间隙占据的空间相同

2.3 justify-content

  • 用于主轴对齐,可选的关键字与align-content相同
  • 可选的关键字:flex-start、flex-end、center、space-between和space-around

3. 伸缩性

  • 伸缩布局的关键是容器中的子元素可以自动缩放,占据容器的空间,这个功能可以用复合属性flex实现。
  • flex由三个属性组成,分别是flex-grow(扩展比率)、flex-shrink(收缩比率)和flex-basis(伸缩基准值)。
  • 当容器宽度大于子元素宽度综合的时候,会形成剩余空间;当容器宽度小于子元素宽度总和时,会形成溢出空间。
  • 伸缩容器中的子元素按照扩展比率分配剩余空间,按收缩比率减小尺寸避免溢出。

3.1 flex-grow

  • 子属性flex-grow的值是数字,
  • 如果容器中所有子元素的flex-grow是1,那么每个元素都将占据相同的空间。
  • 如果将第二个元素的flex-grow设置为2,那么第二个元素占据的空间是其它子元素的两倍。

3.2 剩余空间

如果容器宽度为300px,并且容器中有三个子元素,这三个子元素的flex-basis属性值分别为:50px、80px、100px,那么剩余空间为70px(=300-50-80-100)。

section:nth-child(1) {
    flex: 1 1 50px;
}
section:nth-child(2) {
    flex: 2 2 80px;
}
section:nth-child(3) {
    flex: 3 3 100px;
}
  • flex-grow的总和:1+2+3=6
  • 计算元素最终宽度的公式:
    • 最终宽度= (flex-grow / flex-grow总和) * 剩余空间 + flex-basis
    • 第一个子元素宽度 = 1/6 * 70 + 50 = 61.67
    • 第二个子元素宽度 = 2/6 * 70 + 80 = 103.33
    • 第三个子元素宽度 = 3/6 * 70 + 100 = 135

3.3 溢出空间

如果容器宽度为300px,并且容器中有三个子元素,这三个子元素的flex-basis属性值分别为:100px、130px、150px,那么溢出空间为80px(=100+130+150 - 300)。

section:nth-child(1) {
    flex: 1 1 100px;
}
section:nth-child(2) {
    flex: 2 2 130px;
}
section:nth-child(3) {
    flex: 3 3 150px;
}

根据三个元素的flex-shrink属性:

  • 计算出收缩总和为:1*100+2*130+3*150=810
  • 最终宽度 = flex-basis - (flex-shrink * flex-basis) / 收缩总和 * 溢出空间
    • 第一个元素宽度 = 100 - (1*100)/810 * 80 = 90.12
    • 第二个元素宽度 = 130 - (2*130)/810 * 80 = 104.32
    • 第三个元素宽度 = 150 - (2*150)/810 * 80 = 105.56

4. 显示顺序

元素按照HTML文档中的位置排列,位置在前的先显示,位置在后的后显示。order属性能够改变元素的显示顺序,它的值是一个数字,越小越靠前。

<div class="flex">
    <section style="order:2">1</section>
    <section style="order:1">2</section>
    <section style="order:4">3</section>
    <section style="order:3">4</section>
</div>

按照order指定的顺序显示