文章目录
前言
为什么说是进阶学习,在初识flex布局时,觉得比传统布局好用无数倍。随着经常使用,flex布局的简单使用随手就来,比如:
body {
display: flex;
flex-direction: column/row;
justify-content: center/space-between/...;
align-items: center;
...
}
这种flex布局的基础用法已经熟的不能在熟了,但是flex布局肯定有更强大的用法。以及经常发现flex布局的表现和我们的预期不一样。这是因为对于很多细节的点了解的不清楚,因此,今天对flex布局进行一个总结和提高。
1. 创建一个flex容器
文档中采用了 flexbox
的区域就叫做 flex
容器。为了创建 flex
容器, 我们把一个容器的 display
属性值改为 flex
或者 inline-flex
。 完成这一步之后,容器中的直系子元素就会变为 flex 元素。所有CSS属性都会有一个初始值,所以 flex 容器中的所有 flex 元素都会有下列行为:
- 元素排列为一行 (flex-direction 属性的初始值是 row)。
- 元素从主轴的起始线开始。
- 元素不会在主维度方向拉伸,但是可以缩小。
- 元素被拉伸来填充交叉轴大小。
- flex-basis 属性为 auto。
- flex-wrap 属性为 nowrap。
- 这会让你的元素呈线形排列,并且把自己的大小作为主轴上的大小。如果有太多元素超出容器,它们会溢出而不会换行。如果一些元素比其他元素高,那么元素会沿交叉轴被拉伸来填满它的大小。
点评1:很重要但是以前没注意过的点如下:给一个容器声明flex之后,容器中的 直系 子元素就会变为 flex 元素,这里要注意是直系。且这些flex元素,会带一些初始的flex属性,因此有时候,这些元素的行为和预想的会不一样。
点评2:直系子元素会主动拉伸以填充交叉轴大小。这个之前从未注意过。
点评3:如果有太多元素超出容器,它们会溢出而不会换行。
2. 用flex-wrap实现多行Flex容器
这也是上面点评3的补充:为了实现多行效果,请为父容器的flex-wrap声明为wrap。 现在,如果您的项目太大而无法全部显示在一行中,则会换行显示。
对于flex容器,项目的子元素总宽度大于容器最大宽度。 由于flex-wrap的值设置为wrap,所以项目的子元素换行显示。若将其设置为nowrap,这也是默认值,它们将会缩小以适应容器,因为它们使用的是允许缩小的初始Flexbox值。 如果项目的子元素无法缩小,使用nowrap会导致溢出,或者缩小程度还不够小。
3. 简写属性flex-flow:
可以将 flex-direction
和 flex-wrap
组合为简写属性 flex-flow
,例如:
flex-flow: row-reverse/row/column-reverse/column wrap/no-wrap
4. flex元素上的属性
之前说到,当父容器声明为flex布局后,直系子元素会自动成为flex元素。为了更好的控制flex元素,有三个属性可以用于他们:
- flex-grow
- flex-shrink
- flex-basis
这里不得不先提到一个概念:可用空间 available space。这几个 flex 属性的作用其实就是改变了 flex 容器中的可用空间的行为。
假设在 1 个 500px 的容器中,我们有 3 个 100px 宽的元素,那么这 3 个元素需要占 300px 的宽,剩下 200px 的可用空间。在默认情况下, flexbox 的行为会把这 200px 的空间留在最后一个元素的后面。
如果期望这些元素能自动地扩展去填充满剩下的空间,那么我们需要去控制可用空间在这几个元素间如何分配,这就是元素上的那些 flex 属性要做的事。
4.1 flex-grow
flex-grow 若被赋值为一个正整数, flex 元素会以 flex-basis 为基础,沿主轴方向增长尺寸。这会使该元素延展,并占据此方向轴上的可用空间(available space)。如果有其他元素也被允许延展,那么他们会各自占据可用空间的一部分。
如果我们给上例中的所有元素设定 flex-grow 值为1, 容器中的可用空间会被这些元素平分。它们会延展以填满容器主轴方向上的空间。
flex-grow 属性可以按比例分配空间。如果第一个元素 flex-grow 值为2, 其他元素值为1,则第一个元素将占有2/4(上例中,即为 200px 中的 100px), 另外两个元素各占有1/4(各50px)。
4.2 flex-shrink
该属性只有在flex元素总和超出主轴才会生效
flex-grow属性是处理flex元素在主轴上增加空间的问题,相反flex-shrink属性是处理flex元素收缩的问题。如果我们的容器中没有足够排列flex元素的空间,那么可以把flex元素flex-shrink属性设置为正整数来缩小它所占空间到flex-basis以下。与flex-grow属性一样,可以赋予不同的值来控制flex元素收缩的程度 —— 给flex-shrink属性赋予更大的数值可以比赋予小数值的同级元素收缩程度更大。
在计算flex元素收缩的大小时,它的最小尺寸也会被考虑进去,就是说实际上flex-shrink属性可能会和flex-grow属性表现的不一致。因此,我们可以在文章《控制Flex子元素在主轴上的比例》中更详细地看一下这个算法的原理。
在给 flex-grow 和 flex-shrink 赋值是要注意比例。如果我们给所有flex元素的flex属性赋值为 1 1 200px ,并且希望其中一个元素可以增加到2倍,我们可以给该元素的flex属性赋值为2 1 200px。然而,你也可以选择赋值为flex: 10 1 200px 和 flex: 20 1 200px 。
4.3 flex-basis
flex-basis
定义了该元素的空间大小,该属性的默认值是 auto 。此时,浏览器会检测这个元素是否具有确定的尺寸。 在上面的例子中, 所有元素都设定了宽度(width)为100px,所以 flex-basis 的值为100px。
如果没有给元素设定尺寸,flex-basis
的值采用元素内容的尺寸。这就解释了:我们给只要给Flex元素的父元素声明 display: flex ,所有子元素就会排成一行,且自动分配小大以充分展示元素的内容。
4.4 三者的简写
你可能很少看到 上述三种 属性单独使用,而是混合着写在 flex 简写形式中。 flex 简写形式允许你把三个数值按这个顺序书写 — flex-grow,flex-shrink,flex-basis。
flex的简写也有简写:
-
flex: initial 是把flex元素重置为Flexbox的初始值,它相当于 flex: 0 1 auto。在这里 flex-grow 的值为0,所以flex元素不会超过它们 flex-basis 的尺寸。flex-shrink 的值为1, 所以可以缩小flex元素来防止它们溢出。flex-basis 的值为 auto. Flex元素尺寸可以是在主维度上设置的,也可以是根据内容自动得到的。
-
flex: auto 等同于 flex: 1 1 auto;和上面的 flex:initial 基本相同,但是这种情况下,flex元素在需要的时候既可以拉伸也可以收缩。
-
flex: none 可以把flex元素设置为不可伸缩。它和设置为 flex: 0 0 auto 是一样的。元素既不能拉伸或者收缩,但是元素会按具有 flex-basis: auto 属性的flexbox进行布局。
-
flex: 1 或者 flex: 2 等等。它相当于flex: 1 1 0。元素可以在flex-basis为0的基础上伸缩