参考: 《CSS权威指南》(第四版)
0 前言
布局一直是CSS中最重要的功能。CSS2的时代,float和inline-block布局是主流的布局方式,然而这些布局方式脱离了这些css属性原本设计的初衷,造成理解成本高,同时有诸多局限。flex布局与弹性布局是专为现代web开发设计的布局方式,可以解决很多之前布局方式难以解决的问题。
1 Flex布局是什么
FlexBox,弹性盒布局,顾名思义,就是元素具有弹性,能根据可用空间大小增减尺寸。
2 基本概念
- 弹性盒 :在任何元素上声明
display:flex
或display: inline-flex
便激活弹性盒布局,这个元素就成为了弹性容器
(flex container)。 - 弹性元素 :弹性容器的子元素成为
弹性元素
(flex item)。 - 主轴和交叉轴:flexbox的特性是沿着主轴或者交叉轴对齐之中的元素。
❗注意:**弹性容器内的子元素,都会变为块级元素,**而不管原先是内联还是块级,包括匿名内联元素。
3 弹性容器上属性
弹性容器为其子元素生成弹性格式化上下文,这些子元素不论是DOM节点、文本节点,还是生成的内容,都称为弹性元素。
弹性容器中的绝对定位元素
(position:absolute)
也是弹性元素。
flex-direction
flex-direction
属性决定主轴的方向(即项目的排列方向)。
css
.box { flex-direction: row | row-reverse | column | column-reverse; }
flex-wrap
默认情况下,项目都排在一条线(又称"轴线")上。flex-wrap
属性定义,如果一条轴线排不下,如何换行。
它可能取三个值。
(1)nowrap
(默认):不换行。
(2)wrap
:换行,第一行在上方。
flex-flow
flex-flow
属性是flex-direction
属性和flex-wrap
属性的简写形式,默认值为row nowrap
。
justify-content
justify-content
定义在弹性元素在主轴上的对齐方式。
有5个取值: :::info
flex-start
(默认值):左对齐flex-end
:右对齐center
: 居中space-between
:两端对齐,项目之间的间隔都相等。space-around
:每个项目两侧的间隔相等。所以,项目之间的间隔比项目与边框的间隔大一倍。 :::
align-items
定义弹性元素在交叉轴如何对齐
css
.box {
align-items: flex-start | flex-end | center | baseline | stretch;
}
它可能取5个值。具体的对齐方式与交叉轴的方向有关,下面假设交叉轴从上到下。
flex-start
:交叉轴的起点对齐。flex-end
:交叉轴的终点对齐。center
:交叉轴的中点对齐。baseline
: 项目的第一行文字的基线对齐。stretch
(默认值):如果项目未设置高度或设为auto,将占满整个容器的高度。
align-content
align-content
指定在垂轴方向上如何对齐多行弹性元素。所以align-content
属性值只适用于多行显示的弹性容器,对禁止换行和只有一行的弹性容器没有影响。
align-content
属性与align-items
在取值和相关概念上是一样的,但二者的作用不同,align-items
指定的是每一行中弹性元素的定位方式 。而align-content
属性更类似于justify-content
,只不过它的作用是指定如何在垂轴方向上对齐多行弹性元素。
css
.box {
align-content: flex-start | flex-end | center | space-between | space-around | stretch;
}
该属性可能取6个值。 :::info
flex-start
:与交叉轴的起点对齐。flex-end
:与交叉轴的终点对齐。center
:与交叉轴的中点对齐。space-between
:与交叉轴两端对齐,轴线之间的间隔平均分布。space-around
:每根轴线两侧的间隔都相等。所以,轴线之间的间隔比轴线与边框的间隔大一倍。stretch
(默认值):轴线占满整个交叉轴。 :::
4 容器内子项目属性
order
order
属性定义项目的排列顺序。数值越小,排列越靠前,默认为0。
css
.item { order: <integer>; }
align-self
align-self
属性允许单个项目有与其他项目不一样的对齐方式,可覆盖align-items
属性。默认值为auto
,表示继承父元素的align-items
属性,如果没有父元素,则等同于stretch
。
css
.item {
align-self: auto | flex-start | flex-end | center | baseline | stretch;
}
5 flex 属性(flex的精髓)
控制弹性元素在主轴上的比例 - CSS:层叠样式表 | MDN :::info 弹性布局最突出的一点是能把弹性元素变得具有"弹性"。 ::: flex属性是用于控制弹性元素在主轴方向上的尺寸和伸缩性,flex
属性是flex-basis、flex-grow、flex-shrink的简写,这几个 flex 属性的作用其实就是改变了 flex 容器中的可用空间的行为。
首先我们先来了解下可用空间的概念:
正负可用空间:
假设在 1 个 500px 的容器中,我们有 3 个 100px 宽的元素,那么这 3 个元素需要占 300px 的宽,那么久剩下 200px 的正可用空间 。在默认情况下,flexbox 的行为会把这 200px 的空间留在最后一个元素的后面。
比如说下边这个例子:有一个500px宽的容器,但3个弹性元素都为200px宽,那我们一共需要600px宽,因此就有了100px的负可用空间 。
如果期望这些元素能自动地扩展去填充满剩下的空间,那么我们需要去控制可用空间在这几个元素间如何分配,这就是元素上的那些** flex **属性要做的事。
flex-basis
**flex-basis**
指定了 flex 元素在主轴方向上的初始大小。
💡
flex-basis
属性在任何空间分配发生之前初始化弹性元素的尺寸。 作用与flex-grow和flex-shrink之前
可取以下值:
auto
,默认值。此时弹性元素初始宽度由width决定。比如说你已经给你的元素设置了 200px 的宽,则 200px 就是这个元素的 flex-basis。width
,宽度值,也可以是百分数(相对于弹性容器)。注意如果同时设置了flex-basis和width,flex-basis的优先级更高 ,比如设置了flex-basis为200px,设置width为300px,则最终flex-basis会生效。
flex-grow
flex-grow属性的值为一个数字,默认为0。
flex-grow
用于设置弹性元素在弹性容器中分配正向可用空间的相对比例。
看下边这个例子就可以直观理解flex-grow作用机制:弹性容器宽度为750px,容器内有三个设置了width为100px的弹性元素,此时容器内的正向可用空间为450px。下图中的第一个例子,三个弹性元素的flex-grow都为0,此时弹性元素都不会增大;第二个例子:第三个弹性元素flex-grow为1,此时所有正向空间会分为1份 ,都会分配给第三个元素。第三个例子:正向空间会分为5份,每份90px ,所以第一、二个元素宽度为190px(100+90),第三个元素为370px(100+90×3);
flex-shrink
flex-shrink
用于设置弹性元素在弹性容器中分配负向可用空间的相对比例。
flex 弹性元素的大小
flex 属性
flex属性是flex-grow、flex-shrink、flex-basis的简写。 :::info 💡标准制定人员更推荐始终使用flex简写属性,而不是使用flex-grow等属性。 ::: 常见的flex值有四个,涵盖了最常需要的效果:
- flex:initial,这个值根据width或height属性确定弹性元素的尺寸。相当于flex: 0 1 auto;
- flex: auto,相当于"flex: 1 1 auto。效果与flex:initial类似,不过弹性元素变形是双向的;如果容器空间放不下全部弹性元素,元素将缩小;如果有额外空间,弹性元素将增大;
- **flex: none,**禁止弹性元素变形,相当与flex:0 0 auto;
- flex: number,取单个数值,比如flex: 1相当于 flex: 1 0 0 。此时弹性元素具有弹性,可以增大。常与min-width等限制最小尺寸的属性一起使用。
flex完整语法如下:
- 单值语法
- 一个 flex-grow 的有效值:此时简写会扩展为 flex: 1 0。
- 一个 flex-basis 的有效值:此时简写会扩展为 flex: 1 1 。
- 关键字 none 或者全局关键字之一。
- 双值语法 :
- 第一个值必须是一个 flex-grow 的有效值。
- 第二个值必须是以下之一:
- 一个 flex-shrink 的有效值:此时简写会扩展为 flex: 0。
- 一个 flex-basis 的有效值:此时简写会扩展为 flex: 1 。
- 三值语法 :值必须按照以下顺序指定:
- 一个 flex-grow 的有效值。
- 一个 flex-shrink 的有效值。
- 一个 flex-basis 的有效值。
css
/* 单值,无单位数字:flex-grow flex-basis 此时等于 0。 */
flex: 2;
/* 单值,宽度/高度:flex-basis */
flex: 10em;
flex: 30px;
flex: min-content;
/* 双值:flex-grow | flex-basis */
flex: 1 30px;
/* 双值:flex-grow | flex-shrink */
flex: 2 2;
/* 三值:flex-grow | flex-shrink | flex-basis */
flex: 2 2 10%;
6 与absolute一起使用
分为两种情况:
7 弹性布局的实际案例
两栏/三栏的响应式布局
比如实现这种一栏固定,两栏固定,中间内容框随视口变化。
css
.aside{
flex-grow:0 ;
}
.content{
flex:1
}
流式布局
css
.box {
display: flex;
flex-wrap: wrap;
}
.box div {
width: 100px;
height: 100px;
border: 1px solid;
}
居中对齐
8 总结
- 弹性布局具有很多优势,比如弹性布局内的弹性元素margin不合并,可以轻易实现垂直居中、水平居中等。
- 弹性布局包括主轴和交叉轴
- flex布局有很多属性值,可以分为两类:设置在弹性容器内的属性值和弹性元素上的属性值。
- flex属性是flex布局具有"弹性"的关键。弹性元素的尺寸计算有一套规则,受到flex-basis、flex-grow、flex-shrink等属性共同作用。
- flex布局可以轻易实现水平垂直居中、两栏/三栏响应式布局、流式布局。