CSS 布局_2 Flex弹性盒

Unsplash

弹性盒,是一种布局方式,当页面需要适应不同的屏幕大小以及设备类型时,它依然能确保元素拥有更恰当的排布行为,从定义方面来说,弹性布局是指通过调整其内元素的宽高,从而在任何显示设备上实现对可用显示空间最佳填充的能力,弹性容器扩展其内元素来填充可用空间,或将其收缩来避免溢出

块级布局更侧重于垂直方向、行内布局更侧重于水平方向,与此相对的,弹性盒布局算法是与方向无关的

0. 弹性盒布局介绍

弹性盒布局

弹性容器 (Flex container),包含着弹性项目的父元素,通过设置 display: flex 来定义弹性容器

弹性项目 (Flex item),弹性容器的每个子元素都称为弹性项目

轴(Axis),每个弹性框布局包含两个轴,弹性项目沿其依次排列的那根轴称为主轴 (main axis),垂直于主轴的那根轴称为侧轴 (cross axis)

#box {display: flex;}
#box span {flex: 1;}
.item1 {background-color: coral;height: 100px;}
.item2 {background-color: lightblue;height: 80px;}
.item3 {background-color: khaki;height: 120px;}

<div id="box">
  <span class="item1">1</span>
  <span class="item2">2</span>
  <span class="item3">3</span>
</div>
运行结果

0.5 弹性容器可设置的属性

Flex 容器可设置的属性有:
flex-direction 确立主轴的方向,即项目的排列方向,取值为 row/column
flex-wrap:wrap/nowrap; 定义弹性容器是单行或者多行
flex-flow:row wrap;flex-direction 属性和 flex-wrap 属性的简写形式,决定弹性项目如何排布
justify-content 定义了在当前行上,弹性项目沿主轴如何排布,取值为 flex-start/flex-end/center/space-between/space-around
align-items 定义了在当前行上,弹性项目沿侧轴默认如何排布,取值为 flex-start/flex-end/flex-center
align-content 设置弹性元素在弹性容器的 cross 轴方向上的对齐方式,取值为 flex-start/flex-end/center/space-between/space-around

1. flex-direction 属性

flex-direction 属性,定义主轴方向,即子项的排列方向,默认是水平方向 row,竖直方向为 column

取值 子项排列方式
row 默认值,主轴为水平方向,起点在左端,即左对齐
row-reverse 主轴为水平方向,起点在右端
column 主轴为垂直方向,起点在上沿,即顶对齐
column-reverse 主轴为垂直方向,起点在下沿

2. flex-flow 属性

flex-flow 属性是 flex-directionflex-wrap 的简写,flex-direction 定义弹性盒子元素的排列方向,flex-wrap 属性控制 flex 容器是单行或者多行

flex-wrap 取值 子项排列方式
nowrap 默认值,不换行
wrap 换行,第一行在上方
wrap-reverse 换行,第一行在下方
.box {display: flex;width: 220px;margin: 0;padding: 10px;list-style: none;background-color: #eee;}
.box li {width: 100px;height: 100px;text-align: center;}
#box {flex-flow: row nowrap;}
#box2 {flex-flow: row wrap-reverse;}
#box3 {height: 220px;flex-flow: column wrap-reverse;}

<p>flex-flow:row nowrap</p>
<ul id="box" class="box">
  <li style="background-color: coral;">a</li>
  <li style="background-color: lightblue;">b</li>
  <li style="background-color: khaki;">c</li>
</ul>
<p>flex-flow:row wrap-reverse</p>
<ul id="box2" class="box">
  <li style="background-color: coral;">a</li>
  <li style="background-color: lightblue;">b</li>
  <li style="background-color: khaki;">c</li>
</ul>
<p>flex-flow:column wrap-reverse;</p>
<ul id="box3" class="box">
  <li style="background-color: coral;">a</li>
  <li style="background-color: lightblue;">b</li>
  <li style="background-color: khaki;">c</li>
</ul>
运行结果

3. justify-content 属性

justify-content 属性,用于设置弹性元素在 flex 容器的 main 轴方向上的对齐方式

描述
flex-start 默认值,左对齐
flex-end 右对齐
center 居中
space-between 两端对齐,项目之间的间隔都相等
space-around 每个项目两侧的间隔相等,所以项目之间的间隔比项目与边框的间隔大一倍
#main {width: 500px;height: 300px;border: 1px solid #aaa;display: flex;justify-content:flex-start;}
#main div {width: 70px;height: 70px;}

<div id="main">
  <div style="background-color: coral;"></div>
  <div style="background-color: lightblue;"></div>
  <div style="background-color: khaki;"></div>
  <div style="background-color: pink;"></div>
</div>
justify-content

4. align-items 属性

align-items 属性,用于设置弹性元素在 flex 容器的 cross 轴方向上的对齐方式

描述
flex-start 交叉轴的起点对齐
flex-end 交叉轴的终点对齐
center 交叉轴的中点对齐
baseline 弹性元素的第一行文字的基线对齐
stretch 默认值,如果弹性元素未设置高度或设为 auto,将占满整个容器的高度
#main {width: 500px;height: 300px;border: 1px solid #aaa;display: flex;align-items:flex-start;}
#main div {width: 120px;}

<div id="main">
  <div style="background-color:coral;">年糕</div>
  <div style="background-color:lightblue;">年糕是流行于东亚新年的一种传统美食,中文里年糕与“年高”谐音,有年年高的意思。年糕早期是在年夜用来祭祀神灵及供奉祖先,其后渐渐成为一种农历新年食品。</div>
  <div style="background-color:khaki;">24字社会主义核心价值观</div>
  <div style="background-color:pink;">富强民族文明和谐,自由平等公正法制,爱国敬业诚信友善</div>
</div>
align-items

5. align-content 属性

align-content 属性,定义弹性容器的 cross 轴方向上有额外空间时,调整每一行的对齐方式,当弹性容器只有一行时无效,当设置 flex-wrap:wrap; 并出现换行 [多行] 才生效,该属性与在 main 轴上对齐方式的 justify-content 属性类似

描述
stretch 默认值,轴线占满整个交叉轴
flex-start 与交叉轴的起点对齐
flex-end 与交叉轴的终点对齐
center 与交叉轴的中点对齐
space-between 与交叉轴两端对齐,轴线之间的间隔平均分布
space-around 每根轴线两侧的间隔相等,所以轴线之间的间隔比轴线与边框的间隔大一倍
#main {width: 140px;height: 300px;display: flex;flex-flow: row wrap;align-content: flex-start;border: 1px solid black;}
#main div {width: 70px;height: 70px;}

<div id="main">
  <div style="background-color:coral;"></div>
  <div style="background-color:lightblue;"></div>
  <div style="background-color:khaki;"></div>
  <div style="background-color:pink;"></div>
  <div style="background-color:lightgrey;"></div>
  <div style="background-color:lightgreen;"></div>
</div>
align-content

5.5 Flex 元素可设置的属性

Flex 元素可设置的属性有:
flex-grow 定义项目的放大比例,默认为 0
flex-shrink 定义了项目的缩小比例,默认为 1
felx-basis 定义弹性元素在主轴方向上的初始大小,即子项的宽度
flex 属性,是 flex-growflex-shrinkflex-basis 属性的简写,描述弹性项目的整体的伸缩性,默认值为 1
align-self 定义了单个弹性项目在侧轴上应当如何对齐,这个定义会覆盖由 align-items 所确立的默认值,取值为 flex-start/flex-end/center
order 定义项目的排列顺序,数值越小,排列越靠前,默认为 0

6. flex 属性

flex 属性是 flex-growflex-shrinkflex-basis 属性的简写,描述弹性项目的整体的伸缩性,默认值为 1,即 flex: 0 1 auto;

属性 描述
flex-grow 定义项目的放大比例,默认为 0
flex-shrink 定义了项目的缩小比例,默认为 1
felx-basis 定义了弹性元素在主轴方向上的初始大小,即子项的宽度
.flex {display: flex;width: 600px;margin: 0;padding: 0;list-style: none;}
.flex li:nth-child(1) {width: 200px;background-color: red;}
.flex li:nth-child(2) {flex-grow: 1;width: 50px;background-color: blue;}
.flex li:nth-child(3) {flex-grow: 3;width: 50px;background-color: green;}

<ul class="flex">
  <li>a</li>
  <li>b</li>
  <li>c</li>
</ul>
运行结果

flex-grow 属性的默认值为 0,如果没有显示定义该属性,是不会拥有分配剩余空间权利的

上面的例子中 b,c 两项都定义了 flex-grow 属性,flex 容器的剩余空间分成了 4 份,其中 b 占 1 份,c 占 3 份,即 1:3,flex 容器的剩余空间长度为:600 - 200 - 50 - 50 = 300 px,所以最终 a,b,c 的长度分别为:a: 200px;b: 50 + (300 * 1/4) = 125px;c: 50 + (300 * 3/4) = 275px

.flex {display: flex;width: 400px;margin: 0;padding: 0;list-style: none;}
.flex li:nth-child(1) {width: 200px;background-color: coral;}
.flex li:nth-child(2) {width: 200px;background-color: lightblue;}
.flex li:nth-child(3) {flex-shrink: 3;width: 200px;background-color: khaki;}

<ul class="flex">
  <li>a</li>
  <li>b</li>
  <li>c</li>
</ul>
运行结果

flex-shrink 属性的默认值为 1,如果没有显示定义该属性,将会自动按照默认值 1 在所有子项宽度相加之后计算比率来进行空间收缩

上面的例子中 c 定义了 flex-shrink,a 和 b 没有定义,但会根据默认值 1 来计算,可以看到总共将剩余空间分成了5份,其中 a 占 1 份,b 占 1 份,c 占 3 份,即 1:1:3,我们可以看到父项宽度定义为 400 px,子项被定义为 200 px,相加之后为 600 px,超出父项宽度 200 px,那么这么超出的 200 px 需要被 a,b,c 消化,所以最终 a,b,c 的长度分别为:a: 200 - (200 * 1/5) = 160px;b: 200 - (200 * 1/5) = 160px;c: 200 - (200 * 3/5) = 80px

#box {display: flex;flex-wrap:wrap;}
#box span {flex-basis:20%;height: 100px;color: white;font-size: 48px;background-color: coral;}

<div id="box">
  <span>1</span><span>2</span><span>3</span><span>4</span><span>5</span><span>6</span><span>7</span><span>8</span><span>9</span><span>10</span>
</div>
运行结果

flex-basis 属性的初始值为 auto,设置或检索弹性盒伸缩基准值,如果所有子元素的基准值之和大于剩余空间,则会根据每项设置的基准值,按比率伸缩剩余空间

flex-basis 值为 (25%,33.333%] 时,最多 3 个子项一行,值为 (20%,25%] 时,最多 4 个子项一行,上面的例子中 flex-basis 的值为 20%,即每一个子项占据该行宽度的 20%,一行可排列 5 个子项,但我们一共有 10 个子项,将 10 个子项都排在一行,会导致溢出 flex 容器

所以我们在父级添加了 flex-wrap 属性,指定 flex 元素单行显示还是多行显示,默认不换行,值为 nowrap,指定容器多行显示,值为 wrap,还有一个值为 wrap-reverse,也是多行显示,但是 cross-startcross-end 交替排列,效果如下图所示:

运行结果

7. align-self 属性

align-self 属性,定义 flex 子项单独在 cross 轴方向上的对齐方式,可覆盖 align-items 属性

描述
auto 默认值,元素继承了它的父容器的 align-items 属性,如果没有父容器,则值为 "stretch"
flex-start 位于交叉轴的起点
flex-end 位于交叉轴的终点
center 位于交叉轴的中点
baseline 与基线对齐
stretch 弹性元素被拉伸到与容器相同的高度或宽度
#main {width: 500px;height: 300px;border: 1px solid #aaa;display: flex;align-items: center;}
#main div {width: 120px;}
#main div:nth-child(3) {align-self:flex-start;}

<div id="main">
  <div style="background-color:coral;">年糕</div>
  <div style="background-color:lightblue;">年糕是流行于东亚新年的一种传统美食,中文里年糕与“年高”谐音,有年年高的意思。年糕早期是在年夜用来祭祀神灵及供奉祖先,其后渐渐成为一种农历新年食品。</div>
  <div style="background-color:khaki;">24字社会主义核心价值观</div>
  <div style="background-color:pink;">富强民族文明和谐,自由平等公正法制,爱国敬业诚信友善</div>
</div>
align-self

8. order 属性

order 属性规定了弹性容器中的可伸缩项目在布局时的顺序,元素按照 order 属性的数值的增序进行布局,数值小的排在前面,可以为负值,默认值为 0,拥有相同 order 属性值的元素按照它们在源代码中出现的顺序进行布局

#main {display: flex;background-color: #eee;}
#main div {width: 100px;height: 100px;text-align: center;}
#main div:nth-child(3) {order: -1;}

<div id="main">
  <div style="background-color:coral;">1</div>
  <div style="background-color:lightblue;">2</div>
  <div style="background-color:khaki;">3</div>
  <div style="background-color:pink;">4</div>
  <div style="background-color:lightgrey;">5</div>
  <div style="background-color:lightgreen;">6</div>
</div>
运行结果

参考资料
Flex 布局语法教程

End of File

行文过程中出现错误或不妥之处在所难免,希望大家能够给予指正,以免误导更多人,最后,如果你觉得我的文章写的还不错,希望能够点一下喜欢关注,为了我能早日成为简书优秀作者献上一发助攻吧,谢谢!^ ^

推荐阅读更多精彩内容