Flex (弹性盒布局)
Flexible Box 模型,通常被称为 flexbox,意为”弹性布局”,是一种一维的布局模型。它给 flexbox 的子元素之间提供了强大的空间分布和对齐能力。
flexbox 是一种一维的布局,是因为一个 flexbox 一次只能处理一个维度上的元素布局,一行或者一列。作为对比的是另外一个二维布局 Grid Layout (栅格布局),可以同时处理行和列上的布局。
flexbox 的两根轴线
主轴和交叉轴:主轴由 flex-direction
定义,另一根轴垂直于它。我们使用 flexbox 的所有属性都跟这两根轴线有关。
主轴 :flex-direction属性
flex-direction属性决定主轴的方向(即项目的排列方向)。
主轴由 flex-direction
定义,可以取 4 个值:
row
:主轴为水平方向,起点在左端。row-reverse
::主轴为水平方向,起点在右端。column
:主轴为垂直方向,起点在上沿。column-reverse
:主轴为垂直方向,起点在下沿。
如果你选择了 row
或者 row-reverse
,主轴将沿着 inline 方向延伸。
选择 column
或者 column-reverse
时,主轴会沿着上下方向延伸 — 也就是 block 排列的方向。
交叉轴
交叉轴垂直于主轴,所以如果flex-direction
(主轴) 设成了 row
或者 row-reverse
的话,交叉轴的方向就是沿着列向下的。
如果主轴方向设成了 column
或者 column-reverse
,交叉轴就是水平方向。
Flex 容器
采用了 flex布局的区域就叫做 flex 容器。创建 flex 容器,只需把一个容器的 display
属性值改为 flex
或者 inline-flex
。
完成这一步之后,容器中的直系子元素就会变为 flex 元素(或flex项目)。所有 CSS 属性都会有一个初始值,所以 flex 容器中的所有 flex 元素都会有下列行为:
- 元素排列为一行 (
flex-direction
属性的初始值是row
)。 - 元素从主轴的起始线开始。
- 元素不会在主维度方向拉伸,但是可以缩小。
- 元素被拉伸来填充交叉轴大小。
flex-basis
属性为auto
。flex-wrap
属性为nowrap
。
这会让你的元素呈线形排列,并且把自己的大小作为主轴上的大小。如果有太多元素超出容器,它们会溢出而不会换行。如果一些元素比其他元素高,那么元素会沿交叉轴被拉伸来填满它的大小。
flex 容器的属性
以下6个属性设置在容器上。
- flex-direction
- flex-wrap
- flex-flow
- justify-content
- align-items
- align-content
flex-wrap属性
默认情况下,项目都排在一条线(又称”轴线”)上。flex-wrap属性定义,如果一条轴线排不下,如何换行。
为了实现多行效果,需为属性flex-wrap
添加一个属性值wrap
。现在,如果项目太大而无法全部显示在一行中,则会换行显示。
flex-wrap可以取三个值:
.box{
flex-wrap: nowrap | wrap | wrap-reverse;
}
(1)nowrap(默认):不换行。
(2)wrap:换行,第一行在上方。
(3)wrap-reverse:换行,第一行在下方。
flex-flow属性:简写属性
flex-flow
属性是flex-direction
属性和flex-wrap
属性的简写形式,第一个指定的值为 flex-direction
,第二个指定的值为 flex-wrap
,默认值为row nowrap
。
.box {
flex-flow: <flex-direction> <flex-wrap>;
}
在下面的例子中,将第一个值修改为 flex-direction
的row
, row-reverse
, column
或 column-reverse
, 并将第二个指定值修改为 wrap
或 nowrap
。
.box {
display: flex;
flex-flow: row wrap;
}
<div class="box">
<div>One</div>
<div>Two</div>
<div>Three</div>
</div>
justify-content属性:控制主轴(横轴)上所有 flex 项目的对齐
justify-content属性定义了项目在主轴上的对齐方式。
.box {
justify-content: flex-start | flex-end | center | space-between | space-around;
}
它可能取5个值,具体对齐方式与轴的方向有关。下面假设主轴为从左到右。
flex-start
(默认值):左对齐flex-end
:右对齐center
: 居中space-between
:两端对齐,项目之间的间隔都相等。space-around
:每个项目两侧的间隔相等。所以,项目之间的间隔比项目与边框的间隔大一倍。
align-items属性:控制交叉轴(纵轴)上所有 flex 项目的对齐
align-items属性定义项目在交叉轴上如何对齐。
.box {
align-items: flex-start | flex-end | center | baseline | stretch;
}
它可能取5个值。具体的对齐方式与交叉轴的方向有关,下面假设交叉轴从上到下。
flex-start
:交叉轴的起点对齐。flex-end
:交叉轴的终点对齐。center
:交叉轴的中点对齐。baseline
: 项目的第一行文字的基线对齐。stretch(默认值)
:如果项目未设置高度或设为auto,将占满整个容器的高度。
align-content属性:控制“多条主轴”的 flex 项目在交叉轴的对齐
align-content属性定义了多根轴线的对齐方式。如果项目只有一根轴线,该属性不起作用。
.box {
align-content: flex-start | flex-end | center | space-between | space-around | stretch;
}
该属性可能取6个值。
flex-start
:与交叉轴的起点对齐。flex-end
:与交叉轴的终点对齐。center
:与交叉轴的中点对齐。space-between
:与交叉轴两端对齐,轴线之间的间隔平均分布。space-around
:每根轴线两侧的间隔都相等。所以,轴线之间的间隔比轴线与边框的间隔大一倍。stretch
(默认值):轴线占满整个交叉轴。
flex项目的属性
以下6个属性设置在项目上。
- order
- flex-grow
- flex-shrink
- flex-basis
- flex
- align-self
在考虑这几个属性的作用之前,需要先了解一下 可用空间 (available space) 这个概念。这几个 flex 属性的作用其实就是改变了 flex 容器中的可用空间的行为。同时,可用空间对于 flex 元素的对齐行为也是很重要的。
假设在 1 个 500px 的容器中,有 3 个 100px 宽的元素,那么这 3 个元素需要占 300px 的宽,剩下 200px 的可用空间。在默认情况下,flexbox 的行为会把这 200px 的空间留在最后一个元素的后面。
如果希望这些元素能自动地扩展去填充满剩下的空间,那么就需要去控制可用空间在这几个元素间如何分配,这就是元素(项目)上的那些 flex
属性要做的事。
order属性
order属性定义项目的排列顺序。数值越小,排列越靠前,默认为0。
.item {
order: <integer>;
}
flex-basis属性
flex-basis
定义了该元素的空间大小(the size of that item in terms of the space),flex 容器里除了元素所占的空间以外的富余空间就是可用空间 (available space)。该属性的默认值是 auto
,即项目的本来大小。浏览器会检测这个元素是否具有确定的尺寸。
如果元素设定了宽度(width)为 100px,那么 flex-basis
的值为 100px。
如果没有给元素设定尺寸,flex-basis
的值采用元素内容的尺寸。这就解释了:只要给 Flex 元素的父元素声明 display: flex
,所有子元素就会排成一行,且自动分配大小以充分展示元素的内容。
.item {
flex-basis: <length> | auto; /* default auto */
}
其中length可以设为跟width或height属性一样的值(比如350px),则项目将占据固定空间。
flex-grow属性
flex-grow
若被赋值为一个正整数,flex 元素会以 flex-basis
为基础,沿主轴方向增长尺寸。这会使该元素延展,并占据此方向轴上的可用空间(available space)。如果有其他元素也被允许延展,那么他们会各自占据可用空间的一部分。
flex-grow
属性定义项目的放大比例,默认为0,即如果存在剩余空间,也不放大。
.item {
flex-grow: <number>; /* default 0 */
}
如果给所有元素设定 flex-grow
值为 1,容器中的可用空间会被这些元素平分。它们会延展以填满容器主轴方向上的空间。
flex-grow
属性可以按比例分配空间。如果有一个元素 flex-grow
值为 2,其他元素值为 1,则第一个元素将占有 2/4,另外两个元素各占有 1/4,前者占据的剩余空间将比其他项多一倍。。
flex-shrink属性
flex-grow
属性是处理 flex 元素在主轴上增加空间的问题,相反flex-shrink
属性是处理 flex 元素收缩的问题。
如果我们的容器中没有足够排列 flex 元素的空间,那么可以把 flex 元素flex-shrink
属性设置为正整数来缩小它所占空间到flex-basis
以下。
与flex-grow
属性一样,可以赋予不同的值来控制 flex 元素收缩的程度 。 flex-shrink
属性定义了项目的缩小比例,默认为1,即如果空间不足,该项目将缩小。
如果所有项目的flex-shrink
属性都为1,当空间不足时,都将等比例缩小。如果一个项目的flex-shrink
属性为0,其他项目都为1,则空间不足时,前者不缩小。负值对该属性无效。
flex属性:简写属性
flex
简写形式允许把三个数值按如下顺序书写 — flex-grow
,flex-shrink
,flex-basis
。
flex
属性是flex-grow
, flex-shrink
和 flex-basis
的简写,默认值为0 1 auto。后两个属性可选。
.item {
flex: none | [ <'flex-grow'> <'flex-shrink'>? || <'flex-basis'> ]
}
该属性有两个快捷值:auto (1 1 auto) 和 none (0 0 auto)。
第一个数值是 flex-grow
。赋值为正数的话是让元素增加所占空间。第二个数值是flex-shrink
— 正数可以让它缩小所占空间,但是只有在 flex 元素总和超出主轴才会生效。最后一个数值是 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: <positive-number>
:常看到的flex: 1
或者flex: 2
等等。它相当于flex: 1 1 0
或者flex: 2 1 0
。元素可以在flex-basis
为 0 的基础上伸缩。
align-self:控制交叉轴(纵轴)上的单个 flex 项目的对齐。
align-self
属性允许单个项目有与其他项目不一样的对齐方式,可覆盖align-items
属性。默认值为auto,表示继承父元素的align-items
属性,如果没有父元素,则等同于stretch。
align-self
拥有 align-items
的所有属性值,另外还有一个 auto
能重置自身的值为 align-items
定义的值。
该属性可能取6个值,除了auto,其他都与align-items
属性完全一致。
.item {
align-self: auto | flex-start | flex-end | center | baseline | stretch;
}
在下面的一个例子中,flex 容器为 align-items: flex-start
,这意思是所有的 flex 项目都在交叉轴方向的开始端对齐。用 first-child
选择器给第一个 flex 项目设置了 align-self: stretch
;另外一个 flex 项目用 selected 的类设置成 align-self: center
。
.box {
display: flex;
align-items: flex-start;
height: 200px;
}
.box>*:first-child {
align-self: stretch;
}
.box .selected {
align-self: center;
}
<div class="box">
<div>One</div>
<div>Two</div>
<div class="selected">Three</div>
<div>Four</div>
</div>