FlexBox 弹性盒子布局
介绍
Flexbox 布局(也叫Flex布局,弹性盒子布局)模块旨在提供一个更有效地布局、对齐方式,并且能够使容器中的子元素大小未知或动态变化情况下仍然能够分配好子元素之间的空间。
Flex 布局的主要思想是使父容器能够调节子元素的宽度/高度(和排列顺序),从而能够最好地填充可用空间(主要是为了适应所有类型的显示设备和屏幕尺寸)。
flex布容器能够放大子元素使之尽可能填充可用空间,也可以收缩子元素使之不溢出。
flexbox布局与方向无关,不同于常规布局(基于垂直的块(block)和基于水平的内联(inline))。 虽然传统布局适用于页面,但它们对于大型或复杂的应用程序布局来说缺乏灵活性(特别是在改变方向,调整大小,拉伸,收缩等方面)。
注: Flexbox布局最适合应用程序的组件和小规模布局,而 Gird 布局则适用于较大规模的布局。
基础知识和术语
在flex布局中,flex 项(子元素)要么按照 main axis(主轴)(从 main-start 到 main-end )排布,要么按照cross axis(交叉轴) (从 cross-start 到cross-end)排布。
main axis
flex 容器的主轴,flex 项沿着主轴排布,注意主轴不一定是水平的,主轴是水平还是垂直取决于 flex-direction 属性。
main-start|main-end
分别表示主轴的开始位置和结束位置,flex 项在容器中会从 main-start 到 main-end 排布。
main size
flex 项占据主轴的宽度或高度。flex 项的 main size 属性是要么是“宽度”,要么是“高度”,这取决于主轴方向。
cross axis
垂直于主轴的轴线称为交叉轴,其方向取决于主轴方向。
cross-start|cross-end
分别表示交叉轴的开始位置和结束位置。flex 项在交叉轴上的排布从 cross-start 开始位置到 cross-end 结束位置。
cross size
flex 项占据交叉轴的宽度或高度。flex 项的 cross size 属性是要么是“宽度”,要么是“高度”,这取决于交叉轴方向。
flex容器
容器(container,也可以叫做父元素,称为flex container)
flex项
容器的子元素(item,也可以叫做子元素,称为flex items)
容器(父元素)属性
diplay:flex
用来定义一个 flex 容器。如果设置为 flex 则容器呈现为块状元素,设置为inline-flex 则容器呈现为行内元素。它为所有直接子元素提供了 flex 上下文
.container {
display: flex; /* or inline-flex */
}
flex-direction
flex-direction 属性确立了主轴,从而定义了 flex 项在 flex 容器中的排布方向。
Flexbox 是单向布局,有些时候我们也称作一维布局。 可以将 flex 项视为主要沿着水平行或垂直列排布。
.container {
flex-direction: row | row-reverse | column | column-reverse;
}
属性表:
- row (默认值) :行排布。在 ltr (left to right, 从左到右)排版方式下,flex 项从左到右排列,在 rtl
(right to left, 从右到左)排版方式下,flex 项从右到左排列。 - row-reverse: 反向行排布,即 row 的反方向,在 ltr 中从右向左,在 rtl 中从左到右。
- column: 列排布,与 row 相似,但是 flex 项从上到下排布。
- column-reverse: 反向列排布,即 column 反方向,与 row-reverse 相似,只是 flex 项从上到下排布。
flex-wrap
默认情况下,flex 项会尽可能地尝试排在同一行上(行或列),通过设置 flex-wrap 来决定 flex 项是否允需要换行。
.container{
flex-wrap: nowrap | wrap | wrap-reverse;
}
属性表:
- nowrap (默认值) : 所有的 flex 项都会在同一行上排布,也就是我们常说的单行,或不换行。
- wrap: flex 项将从上到下根据实际情况排布再多行上,也就是我们常说的多行,或会换行。
- wrap-reverse: flex 项将 从下到上 根据实际情况排布再多行上折行。
flex-flow (适用于父级 flex 容器)
这是 flex-direction 和 flex-wrap 属性的缩写形式。
同时定义 flex 容器的主轴和交叉轴。默认是 row nowrap
flex-flow: <‘flex-direction’> || <‘flex-wrap’>
justify-content
justify-content 属性定义了flex 项沿主轴方向的对齐方式
当一行中的所有 flex 项都是固定大小,或者是灵活大小但已经达到最大 main size 时,它可以帮助分配主轴上的剩余空间。当 flex 项溢出主轴的时候,它还可以用来控制flex 项的对齐方式。
.container {
justify-content: flex-start | flex-end | center | space-between | space-around | space-evenly;
}
属性表
-
flex-start (默认值) : flex 项从主轴的开始位置(main-start)开始排布。
- -
flex-end : flex 项从主轴的结束位置(main-end)开始排布
- -
center: flex 项沿主轴居中排布
- -
space-between: flex 项沿主轴均匀排布,即我们常说的沿主轴 两端对齐 ,第一个flex
项在主轴开始位置,最后一个flex 项在主轴结束位置。
-
space-around: flex 项沿主轴均匀排布。要注意的是 flex 项看起来间隙是不均匀的,因为所有 flex
项两边的空间是相等的。第一项在容器边缘有一个单位的空间,但是在两个 flex 项之间有两个单位的间隙,因为每个 flex 项的两侧都有一个单位的间隙。
-
space-evenly: 任何两个 flex 项之间的间距(以及到 flex 容器边缘的空间)相等。
-
align-items
align-items 定义了 flex 项如何沿当前行在交叉轴上排布的默认行为。可以将其视为交叉轴(垂直于主轴)上的对齐方式。
.container {
align-items: flex-start | flex-end | center | baseline | stretch;
}
属性表:
-
flex-start: flex 项按照交叉轴的开始位置(cross-start)对齐
- -
flex-end: flex 项按照交叉轴的结束位置(cross-end)对齐
- -
center: flex 项以交叉轴为中心,居中对齐
- -
baseline: flex 项按照他们的文字基线对齐
- -
stretch (默认值) : 拉伸 flex 项以填充整个容器(这里特别要注意:如果 flex 项有尺寸属性(min-width /
max-width / width / min-height / max-height / height),那么首先应用这些尺寸属性)
align-content
当交叉轴上有剩余空间时,align-content 可以设置 flex 容器中的 行 在交叉轴上如何分配剩余空间,类似于 justify-content 在主轴上对齐单个 flex 项的方式。
注:当只有一行flex项时,此属性不起作用
.container {
align-content: flex-start | flex-end | center | space-between | space-around | stretch;
}
属性表
- flex-start:多行在容器的开始位置排布
- - flex-end:多行在容器的结束位置排布
- - center:多行在容器的总结位置排布
- - space-between:多行均匀分布;第一行分布在容器的开始位置,最后一行分布在容器的结束位置
- - space-around: 多行均匀分布,并且每行的间距(包括离容器边缘的间距)相同;
- - strech (默认值):多行拉伸以填充满整个剩余空间
-
项属性(flex items)
order
默认情况下,flex 项按源(HTML结构)顺序排布。但是,order 属性可以控制它们在 flex 容器中的显示顺序
.item {
order: <integer>; /* 默认值是 0 */
}
flex-grow
flex-grow 定义了 flex 项在有可用剩余空间时拉伸比例。
它接受的值作为比例,无单位。它规定了 flex 项应该占 flex 容器中可用空间的比例。
如果所有 flex 项的 flex-grow 都设置为 1 ,则父容器中的剩余空间将平均分配给所有子项。 如果其中一个子项的值为 2 ,则该子项占用的剩余空间是其他子项的两倍(或者至少会尽力获得)。
.item {
flex-grow: <number>; /* default 0 */
}
注:负值对flex-grew无效
flex-shrink
flex-shrink 定义了 flex 项的收缩的能力。
(注:与 flex-grow 拉伸正好相反,flex-shrink 决定 flex 项允许收缩多少比例。)
.item {
flex-shrink: <number>; /* default 1 */
}
注:负值对于 flex-shrink 无效
flex-basis
flex-basis 定义了在分配剩余空间之前 flex 项默认的大小。
可以设置为某个长度值**(e.g. 20%, 5rem,等)**或者关键字。
关键字 auto
意味着 flex 项会按照其本来的大小显示(暂时由 main-size 关键字完成,直到弃用)。
关键字 content
意味着根据内容来确定大小——这个关键字到目前没有被很好地支持,所以测试起来比较困难,与content的类似的关键字还有max-content, min-content, fit-content。
.item {
flex-basis: <length> | auto; /* default auto */
}
注:如果设置为 0 , 则 flex 项内容周围的空隙不会根据 flex-grow 按比例分配,如果设置为 auto,则 flex 项周围额外的空袭会根据 flex-grow 按照比例分配
flex
flex 是 flex-grow、flex-shrink、flex-basis 三个属性的缩写。
其中第二个和第三个参数(flex-shrink 和 flex-basis)是可选的。默认值为0 1 auto。
.item {
flex: none | [ < 'flex-grow'> < 'flex-shrink'>? || < 'flex-basis'> ]
}
align-self
align-self 属性允许某个单独的 flex 项覆盖默认的对齐方式(或由 align-items 指定的对齐方式)。
.item {
align-self: auto | flex-start | flex-end | center | baseline | stretch;
}
示例
水平垂直居中
HTML
<ul class="flex-container">
<li class="flex-item">1</li>
<li class="flex-item">2</li>
<li class="flex-item">3</li>
<li class="flex-item">4</li>
<li class="flex-item">5</li>
<li class="flex-item">6</li>
</ul>
css
.flex-container {
/* We first create a flex layout context */
display: flex;
/* Then we define the flow direction
and if we allow the items to wrap
* Remember this is the same as:
* flex-direction: row;
* flex-wrap: wrap;
*/
flex-flow: row wrap;
/* Then we define how is distributed the remaining space */
justify-content: space-around;
padding: 0;
margin: 0;
list-style: none;
}
.flex-item {
background: tomato;
padding: 5px;
width: 200px;
height: 150px;
margin-top: 10px;
line-height: 150px;
color: white;
font-weight: bold;
font-size: 3em;
text-align: center;
}
导航栏
假设我们有一个向右对齐的导航栏在我们网页的最上端,但是我们希望它在中屏上显示时为居中,在小屏上显示为单列。
css
.navigation {
display: flex;
flex-flow: row wrap;
justify-content: flex-end;
list-style: none;
margin: 0;
background: deepskyblue;
}
.navigation a {
text-decoration: none;
display: block;
padding: 1em;
color: white;
}
.navigation a:hover {
background: #1565C0;
}
@media all and (max-width: 800px) {
.navigation {
justify-content: space-around;
}
}
@media all and (max-width: 600px) {
.navigation {
flex-flow: column wrap;
padding: 0;
}
.navigation a {
text-align: center;
padding: 10px;
border-top: 1px solid rgba(255, 255, 255,0.3);
border-bottom: 1px solid rgba(0, 0, 0, 0.1);
}
.navigation li:last-of-type a {
border-bottom: none;
}
}