CSS 布局_2 Flex弹性盒

2024-03-19 17:00:58 浏览数 (2)

UnsplashUnsplash

弹性盒,是一种布局方式,当页面需要适应不同的屏幕大小以及设备类型时,它依然能确保元素拥有更恰当的排布行为,弹性盒属于 CSS 3 部分,IE9 以下不支持,现代浏览器指的就是 IE9 及以上的浏览器

在定义方面来说,弹性布局是指通过调整其内元素的宽高,从而在任何显示设备上实现对可用显示空间最佳填充的能力,弹性容器扩展其内元素来填充可用空间,或将其收缩来避免溢出

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

弹性盒布局介绍

弹性盒布局弹性盒布局

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

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

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

flex-direction; 确立主轴

justify-content; 定义了在当前行上,弹性项目沿主轴如何排布

align-items; 定义了在当前行上,弹性项目沿侧轴默认如何排布

align-self; 定义了单个弹性项目在侧轴上应当如何对齐,这个定义会覆盖由 align-items 所确立的默认值

方向 (Direction),弹性容器的主轴起点 (main start) / 主轴终点 (main end)侧轴起点 (cross start) / 侧轴终点 (cross end)描述了弹性项目排布的起点与终点,它们具体取决于弹性容器的主轴与侧轴中,由 writing-mode; 确立的方向(从左到右、从右到左,等等)

order 属性,将元素与序号关联起来,以此决定哪些元素先出现。

flex-flow 属性,是 flex-directionflex-wrap 属性的简写,决定弹性项目如何排布

行 (Line),根据 flex-wrap 属性,弹性项目可以排布在单个行或者多个行中,该属性控制侧轴的方向和新行排列的方向

尺寸 (Dimension),根据弹性容器的主轴与侧轴,弹性项目的宽和高中,对应主轴的称为主轴尺寸 (main size) ,对应侧轴的称为 侧轴尺寸 (cross size)

min-heightmin-width 属性初始值将为 0

flex 属性,是 flex-growflex-shrinkflex-basis 属性的简写,描述弹性项目的整体的伸缩性

代码语言:javascript复制
#box {
  display: flex;
  flex-direction: row;
}
#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>
运行结果运行结果

如果将 box 的属性改为

代码语言:javascript复制
#box {
  display: flex;
  align-items: center;
}
运行结果运行结果

flex 属性

display:flex; 设置在外层容器父级,表示该容器使用弹性盒布局方式

flex:1; 设置在子项,数值表示占据剩余空间的份数

flex 属性,是以下三个属性的简写,即 flex:0 1 auto;

属性

描述

flex-grow:0;

定义弹性盒子项的拉伸因子,即子项分配父项剩余空间的比,默认值为 0

flex-shrink:1;

指定了 flex 元素的收缩规则,子项的收缩所占的份数,默认值为1 当所有子项相加的宽度大于父项的宽度,每个子项减少的多出的父项宽度的 1/n

felx-basis:auto;

指定了 flex 元素在主轴方向上的初始大小,即子项的宽度

代码语言:javascript复制
.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

代码语言:javascript复制
.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

代码语言:javascript复制
#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 交替排列,效果如下图所示:

运行结果运行结果

flex-direction 属性

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

取值

子项排列方式

row

flex 容器的 main 轴与行内轴方向作为默认的书写模式,即横向从左到右排列(左对齐)

row-reverse

表现和 row 相同,但是置换了 main 轴起点和 main 轴终点

column

flex 容器的 main 轴与块轴方向作为默认的书写模式,即纵向从上往下排列(顶对齐)

column-reverse

表现和 column 相同,但是置换了 main 轴起点和 main 轴终点

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

代码语言:javascript复制
.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>
运行结果运行结果

justify-content 属性

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

描述

flex-start

从行首开始排列,每行第一个弹性元素与行首对齐,同时所有后续的弹性元素与前一个对齐

flex-end

从行尾开始排列,每行最后一个弹性元素与行尾对齐,其他元素将与后一个对齐

center

伸缩元素向每行中点排列,每行第一个元素到行首的距离将与每行最后一个元素到行尾的距离相同

space-between

在每行上均匀分配弹性元素,相邻元素间距离相同,即空白在子项之间每行第一个元素与行首对齐,每行最后一个元素与行尾对齐

space-around

在每行上均匀分配弹性元素,相邻元素间距离相同,即空白围绕着子项每行第一个元素到行首的距离和每行最后一个元素到行尾的距离将会是相邻元素之间距离的一半

代码语言:javascript复制
#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:flex-start;justify-content:flex-start;
justify-content:flex-end;justify-content:flex-end;
justify-content:center;justify-content:center;
justify-content:space-between;justify-content:space-between;
justify-content:space-around;justify-content:space-around;

align-items 属性

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

描述

flex-start

元素紧靠 cross 轴起始边界

flex-end

元素紧靠 cross 轴结束边界

center

元素在 cross 轴居中,如果元素在 cross 轴上的高度高于其容器,那么在两个方向上溢出距离相同

baseline

所有元素向基线对齐, cross 轴起点到元素基线距离最大的元素将会于 cross 轴起点对齐以确定基线

stretch

弹性元素被在 cross 轴方向被拉伸到与容器相同的高度或宽度

代码语言:javascript复制
#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:flex-start;align-items:flex-start;
align-items:flex-end;align-items:flex-end;
align-items:center;align-items:center;
align-items:baseline;align-items:baseline;
align-items:stretch;align-items:stretch;

align-self 属性

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

描述

auto

默认值,元素继承了它的父容器的 align-items 属性,如果没有父容器,则值为 "stretch"

flex-start

元素位于该行的 cross 轴的起始边界

flex-end

元素位于该行的 cross 轴的结束边界

center

元素在该行的 cross 轴居中如果元素在 cross 轴上的高度高于其容器,那么在两个方向上溢出距离相同

baseline

如果弹性盒元素的行内轴与 cross 轴为同一条,则该值与 "flex-start" 等效其它情况下,该值将参与基线对齐

stretch

元素被拉伸到与容器相同的高度或宽度

代码语言:javascript复制
#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:auto;align-self:auto;
align-self:flex-start;align-self:flex-start;
align-self:flex-end;align-self:flex-end;
align-self:center;align-self:center;
align-self:baseline;align-self:baseline;
align-self:stretch;align-self:stretch;

align-content 属性

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

描述

stretch

拉伸所有行来填满剩余空间,剩余空间平均的分配给每一行

flex-start

所有行从 cross 轴起始位置开始堆叠第一行的 cross 轴起始边界紧靠容器的 cross 轴起始边界,接下来的每一行紧跟前一行

flex-end

所有行从 cross 轴结束位置开始堆叠第一行的 cross 轴结束边界紧靠容器的 cross 轴结束边界,接下来的每一行紧跟前一行

center

所有行朝向容器的中心填充,每行互相紧挨,相对于容器居中对齐容器的 cross 轴起始边界和第一行的距离相等于容器的 cross 轴结束边界和最后一行的距离

space-between

所有行在容器中平均分布,相邻两行间距相等容器的 cross 轴起始边界和结束边界分别与第一行和最后一行的边对齐

space-around

所有行在容器中平均分布,相邻两行间距相等容器的 cross 轴起始边界和结束边界分别与第一行和最后一行的距离是相邻两行间距的一半

代码语言:javascript复制
#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:stretch;align-content:stretch;
align-content:flex-start;align-content:flex-start;
align-content:flex-end;align-content:flex-end;
align-content:center;align-content:center;
align-content:space-between;align-content:space-between;
align-content:space-around;align-content:space-around;

order 属性

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

代码语言:javascript复制
#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>
运行结果运行结果

父项设置:

display:flex;

flex-wrap:wrap/nowrap;

flex-direction:row/column;

flex-flow:wrap row;

justify-content:flex-start/flex-end/center/space-between/space-around;

align-items:flex-start/flex-end/flex-center;

align-content: flex-start/flex-end/center/space-between/space-around;

子项设置:

flex:1;

flex-grow:1;

flex-shrink:1;

felx-basis:auto;

align-self:flex-start/flex-end/center;

order:-1;

0 人点赞