Flex 弹性伸缩
Flex 元素除了基本的设定和对齐,也可以借由作用于“弹性项目”的 flex、flex-grow、flex-shrink、flex-basis 样式属性,制造出可以根据不同的父元素宽度,进行“自由伸缩、弹性伸缩”的弹性项目,除此之外,也会透过弹性项目专用的 order 样式属性,改变弹性项目位置,这篇教学会介绍这些样式属性的用法。
相关文章:认识弹性盒子 Flexbox、Flex 的对齐方式
快速导览:
flex-grow 弹性项目扩展比例
flex-grow 样式属性会设定“弹性项目的扩展比例”,属性值只支援“没有单位、非负值的数值”,默认值为 0,可以使用浮点数,没有继承特性,使用后弹性项目会根据所设定的数值,自动分配弹性容器扣除未设定扩展比例的弹型项目内容空间的“剩余空间”,计算公式如下 ( 宽度表示元素容器盒子的外边界范围 ):
下方范会使用两组 div,按照下列规则撰写 CSS,可以看出第二组和第三组的第四个 div,不论 flex-grow 数值为何,都会撑满容器,而第一组只会保留自己的空间:
- 假设弹性容器宽度 400px。
- 内容有三个未设定扩展比例的弹性项目、一个设定
flex-grow:1的弹性项目。- 假设三个未设定弹性项目的“内容与边界”加起来共有 100px。
- 弹性容器宽度减去上述的 100px 还有 300px。
- 有设定
flex-grow:1的弹性项目分配到 (300x1)/1,也就是“300px + 自己的容器空间”。- 有设定
flex-grow:4的弹性项目分配到 (300x4)/4,也就是“300px + 自己的容器空间”。
<!-- HTML 程式碼-->
<div class="f g1"><div>o</div><div>o</div><div>o</div><div>o</div></div>
<div class="f g2"><div>o</div><div>o</div><div>o</div><div>o</div></div>
<div class="f g3"><div>o</div><div>o</div><div>o</div><div>o</div></div>
<!-- CSS 程式碼 -->
<style>
.f {
width: 400px;
height: 50px;
border: 1px solid #000;
display: flex;
font-size: 24px;
margin: 20px;
}
div div {padding: 5px 0px;}
div div:nth-child(1) {background: #f33;}
div div:nth-child(2) {background: #fb0;}
div div:nth-child(3) {background: #4cf;}
div div:nth-child(4) {background: #0b0;}
.g2 div:nth-child(4) {flex-grow: 1;} /* 第二組的第四個 div 設定彈性擴展 */
.g3 div:nth-child(4) {flex-grow: 4;} /* 第三組的第四個 div 設定彈性擴展 */
</style>
如果两个以上的弹性项目设定了 flex-grow,则同样会按照计算公式计算弹性项目宽度,下方范例的第三个和第四个 div,会按照下方公式分配宽度 ( 假设剩余空间为 300px ):
- 第三个 div (
flex-grow:1):300 x 1 / ( 2 + 1 ) = 100- 第四个 div (
flex-grow:2):300 x 2 / ( 2 + 1 ) = 200
<!-- HTML 程式碼-->
<div class="f g1"><div>o</div><div>o</div><div>o</div><div>o</div></div>
<!-- CSS 程式碼 -->
<style>
.f {
width: 400px;
height: 50px;
border: 1px solid #000;
display: flex;
font-size: 24px;
margin: 20px;
}
div div {padding: 5px 0px;}
div div:nth-child(1) {background: #f33;}
div div:nth-child(2) {background: #fb0;}
div div:nth-child(3) {background: #4cf;}
div div:nth-child(4) {background: #0b0;}
.g1 div:nth-child(3) {flex-grow: 1;} /* 第三個 div 設定彈性擴展 */
.g1 div:nth-child(4) {flex-grow: 2;} /* 第四個 div 設定彈性擴展 */
</style>
如果有“设定宽度”或“内容宽度较大”的弹性项目,则同样会按照计算公式,先减去原本的宽度,再按照比例分配剩下的空间,下方的范例有三组 div,第一组原本的内容宽度都相,第二组的第四个 div 因为字元较多所以内容较宽,第三组的第三个 div 有设定宽度。
<!-- HTML 程式碼-->
<div class="f g1"><div>o</div><div>o</div><div>o</div><div>o</div></div>
<div class="f g2"><div>o</div><div>o</div><div>o</div><div>oxxo</div></div>
<div class="f g3"><div>o</div><div>o</div><div>o</div><div>o</div></div>
<!-- CSS 程式碼 -->
<style>
.f {
width: 400px;
height: 50px;
border: 1px solid #000;
display: flex;
font-size: 24px;
margin: 20px;
}
div div {padding: 5px 0px;}
div div:nth-child(1) {background: #f33;}
div div:nth-child(2) {background: #fb0;}
div div:nth-child(3) {background: #4cf;}
div div:nth-child(4) {background: #0b0;}
.g1 div:nth-child(3) {flex-grow: 1;}
.g1 div:nth-child(4) {flex-grow: 2;}
.g2 div:nth-child(3) {flex-grow: 1;}
.g2 div:nth-child(4) {flex-grow: 2;}
.g3 div:nth-child(3) {
flex-grow: 1;
width: 100px;
}
.g3 div:nth-child(4) {flex-grow: 2;}
</style>
flex-shrink 弹性项目缩小比例
flex-shrink 样式属性会设定“弹性项目的缩小比例”,属性值只支援“没有单位、非负值的数值”,默认值为 1,可以使用浮点数,没有继承特性,如果 flex-grow 样式属性是分配“剩余的空间”,flex-shrink 样式属性就是分配“溢出弹型容器的空间”,计算公式如下 ( 宽度表示元素容器盒子的外边界范围 ):
下方范例有两组 div,分别呈现 flex-shrink 属性值为 0 和 1 的差异。
<!-- HTML 程式碼-->
<div class="f g1"><div></div><div></div><div></div><div></div><div></div></div>
<div class="f g2"><div></div><div></div><div></div><div></div><div></div></div>
<!-- CSS 程式碼 -->
<style>
.f {
width: 400px;
height: 50px;
border: 1px solid #000;
display: flex;
font-size: 24px;
margin: 20px ;
}
div div {
padding: 5px 0px;
width: 100px;
}
div div:nth-child(1) {background: #f55;}
div div:nth-child(2) {background: #fb0;}
div div:nth-child(3) {background: #4cf;}
div div:nth-child(4) {background: #0b0;}
div div:nth-child(5) {background: #a6f;}
.g1 div {flex-shrink: 0;}
.g2 div {flex-shrink: 1;}
</style>
下方范例的第二组 div 的第四个子元素,因为设定了 flex-shrink:6,多出来的部分就会除以 10 ( 1+1+1+6+1 ),而设定 6 的子元素就会扣除 6/10 多余的部分。
<!-- HTML 程式碼-->
<div class="f g1"><div></div><div></div><div></div><div></div><div></div></div>
<div class="f g2"><div></div><div></div><div></div><div></div><div></div></div>
<!-- CSS 程式碼 -->
<style>
.f {
width: 400px;
height: 50px;
border: 1px solid #000;
display: flex;
font-size: 24px;
margin: 20px ;
}
div div {
padding: 5px 0px;
width: 100px;
}
div div:nth-child(1) {background: #f55;}
div div:nth-child(2) {background: #fb0;}
div div:nth-child(3) {background: #4cf;}
div div:nth-child(4) {background: #0b0;}
div div:nth-child(5) {background: #a6f;}
.g1 div {flex-shrink: 0;}
.g2 div:nth-child(4) {flex-shrink: 6;}
</style>
下方范例展示如果“弹性项目未设定宽度”,内容就会自动撑开容器,这时不论如何设定 flex-shrink 都不会自动分配多出来的宽度。
<!-- HTML 程式碼-->
<div class="f g1"><div>oxxo.studio</div><div>oxxo.studio</div><div>oxxo.studio</div><div>oxxo.studio</div><div>oxxo.studio</div></div>
<div class="f g2"><div>oxxo.studio</div><div>oxxo.studio</div><div>oxxo.studio</div><div>oxxo.studio</div><div>oxxo.studio</div></div>
<div class="f g3"><div>oxxo.studio</div><div>oxxo.studio</div><div>oxxo.studio</div><div>oxxo.studio</div><div>oxxo.studio</div></div>
<!-- CSS 程式碼 -->
<style>
.f {
width: 400px;
height: 50px;
border: 1px solid #000;
display: flex;
font-size: 24px;
margin: 20px ;
}
div div {padding: 5px 0px;} /* 彈性項目未設定寬度,讓內容自動撐開容器 */
div div:nth-child(1) {background: #f55;}
div div:nth-child(2) {background: #fb0;}
div div:nth-child(3) {background: #4cf;}
div div:nth-child(4) {background: #0b0;}
div div:nth-child(5) {background: #a6f;}
.g1 div {flex-shrink: 0;}
.g2 div {flex-shrink: 1;}
.g3 div:nth-child(4) {flex-shrink: 6;}
</style>
flex-basis 弹性项目基础比例
flex-basis 样式属性会设定“弹性项目的基础比例”,属性值只支援“具有单位且非负值的数值或关键字”,没有继承特性,下方列出可用的单位与关键字:
| 单位或关键字 | 说明 |
|---|---|
| px | 绝对长度单位。 |
| % | 相对长度单位,数值为弹性容器宽度的百分比。 |
| auto | 自动调整比例 ( 默认值 )。 |
| 0 | 所有弹性元素都设定为 0 时等于 auto。 |
| content | 由内容决定宽度。 |
使用 flex-basis 时会有下列两种情况,分别会产生不同的效果 ( 下方“宽度”表示默认的水平排列,如果改成垂直排列则是“高度” ):
- 弹性容器空间 > 弹性项目总宽度:
flex-basis属性值为弹性项目宽度。- 弹性容器空间 < 弹性项目总宽度:根据
flex-basis属性值、本身长度、容器宽度换算实际宽度。
下方范例有四个转换成弹性盒子的 div 群组,所有群组中第一个红色 div 设定为 flex-basis: 50%;,第二个橘黄色 div 设定为 flex-basis: 100px;,第三第四的蓝色绿色 div 设定为 flex-basis: 10px;,最后一个紫色 div 设定为 width: 10px;,执行后可以看到下列结果:
- 前两组 div 是“弹性容器空间 > 弹性项目总宽度”,
flex-basis的属性值等于弹性项目的宽度。- 后两个 div 是“弹性容器空间 < 弹性项目总宽度”,就会按照图片说明的公式计算最后的结果。
flex-basis对于弹性项目而言,设定数值后的效果与width相同。
<!-- HTML 程式碼-->
<h3>彈性容器空間 > 彈性項目總寬度</h3>
<div class="f g1"><div></div><div></div><div></div><div></div><div></div></div>
<div class="f g2"><div></div><div></div><div></div><div></div><div></div></div>
<h3>彈性容器空間 < 彈性項目總寬度</h3>
<div class="f g3"><div></div><div></div><div></div><div></div><div></div></div>
<div class="f g4"><div></div><div></div><div></div><div></div><div></div></div>
<!-- CSS 程式碼 -->
<style>
.f {
width: 400px;
height: 50px;
border: 1px solid #000;
display: flex;
font-size: 24px;
margin: 20px ;
}
div div {padding: 5px 0px;}
div div:nth-child(1) {background: #f55;}
div div:nth-child(2) {background: #fb0;}
div div:nth-child(3) {background: #4cf;}
div div:nth-child(4) {background: #0b0;}
div div:nth-child(5) {background: #a6f;}
div div:nth-child(1) {flex-basis: 50%;}
div div:nth-child(2) {flex-basis: 100px;}
div div:nth-child(3) {width: 10px;}
div div:nth-child(4) {width: 10px;}
div div:nth-child(5) {flex-basis: 10px;}
.g2 {width:300px;}
.g3 {width:200px;}
.g4 {width:100px;}
</style>
flex 弹性伸缩 ( 缩写格式 )
flex 是 flex-grow、flex-shrink 和 flex-basis 三个样式属性的缩写样式,三个样式之间使用“空白分隔”,这个样式属性作用于“弹性项目”,没有继承特性,写法如下:
div {
flex: flex-grow flex-shrink flex-basis;
/* 擴展 縮小 基礎 */
}
使用 flex 时除了撰写三个属性值,也可以透过四种“关键字”对应默认的缩写属性值,默认值为 initial,下方列出四种关键字对应的属性值:
| 关键字 | 对应属性值 | 弹性项目总长未超过容器时 | 弹性项目总长溢出容器时 |
|---|---|---|---|
| initial | 0 1 auto | 维持原宽度 ( 无弹性 ) | 缩小填满容器 |
| auto | 1 1 auto | 扩展填满容器 | 缩小填满容器 |
| none | 0 0 auto | 维持原宽度 ( 无弹性 ) | 维持原宽度 ( 无弹性 ) |
| 非负值数字 | 非负值数字 0 0 | 扩展填满容器 | 消失 |
下方范例展示使用 0 作为关键字所产生的弹性伸缩效果,由于蓝绿紫三个 div 加起来宽度为 100px,所以剩余的 100px 就由红黄两个 div 按照比例分配,因为设定 flex: 0 之后第三个数值为 0,等于 flex-basis: 0,在其他弹性项目不为 0 的状态下,若还有剩余空间就会按照比例分配,若没有剩余空间,该弹性项目就会消失。
<!-- HTML 程式碼-->
<h3>彈性容器空間 > 彈性項目總寬度</h3>
<div class="f g1"><div></div><div></div><div></div><div></div><div></div></div>
<div class="f g2"><div></div><div></div><div></div><div></div><div></div></div>
<h3>彈性容器空間 < 彈性項目總寬度</h3>
<div class="f g3"><div></div><div></div><div></div><div></div><div></div></div>
<!-- CSS 程式碼 -->
<style>
.f {
width: 400px;
height: 50px;
border: 1px solid #000;
display: flex;
font-size: 24px;
margin: 20px ;
}
div div {padding: 5px 0px;}
div div:nth-child(1) {background: #f55;}
div div:nth-child(2) {background: #fb0;}
div div:nth-child(3) {background: #4cf;}
div div:nth-child(4) {background: #0b0;}
div div:nth-child(5) {background: #a6f;}
.g1 div {width: 100px;} /* g1 的彈性項目預設寬度 100px,容器還剩餘 100px */
.g1 div:nth-child(1) {flex: 1;} /* 等於 flex: 1 0 0; */
.g1 div:nth-child(2) {flex: 2;} /* 等於 flex: 2 0 0; */
.g2 div {width: 100px;} /* g2 的彈性項目預設寬度 100px,容器還剩餘 100px */
.g2 div:nth-child(1) {flex: 1 0 0;} /* 等於 flex: 1; */
.g2 div:nth-child(2) {flex: 2 0 0;} /* 等於 flex: 2; */
.g3 div {width: 200px;} /* g3 的彈性項目預設寬度 200px,溢出容器 100px */
.g3 div:nth-child(1) {flex: 1;} /* 等於 flex: 1 0 0; */
.g3 div:nth-child(2) {flex: 2;} /* 等於 flex: 2 0 0; */
</style>
下方范例展示了一个“非常弹性”的弹性排版,搭配“文字换行”和“内容溢出裁切”的样式,就能在不同宽度的父元素显示状态下,展现不同的弹性项目宽度,实现的效果如下:
| 元素 | 样式 | 弹性容器有空间时 | 溢出弹性容器空间时 |
|---|---|---|---|
| 红色 div | flex: 1 0 0; |
按照红 1 黄 5 增加空间 | 消失 |
| 黄色 div | flex: 5 0 0; |
按照红 1 黄 5 增加空间 | 消失 |
| 蓝色 div | flex: 0 1 80px; |
维持 50px | 按照蓝 1 绿 5 扣掉空间 |
| 绿色 div | flex: 0 5 80px; |
维持 100px | 按照蓝 1 绿 5 扣掉空间 |
| 紫色 div | flex: 0 0 50%; |
随时保持 50% 容器宽度 | 随时保持 50% 容器宽度 |
<!-- HTML 程式碼-->
<div class="f"><div>oxxo</div><div>oxxo</div><div>oxxo</div><div>oxxo</div><div>oxxo</div></div>
<!-- CSS 程式碼 -->
<style>
.f {
width: 300px;
height: 100px;
border: 1px solid #000;
display: flex;
font-size: 24px;
margin: 20px ;
resize: both; /* 可用滑鼠拖拉縮放 div */
overflow: auto; /* 搭配 resize 一起用 */
}
div div {
padding: 5px 0px;
width: 60px;
overflow-wrap:break-word;
overflow: hidden;
}
div div:nth-child(1) {background: #f55;}
div div:nth-child(2) {background: #fb0;}
div div:nth-child(3) {background: #4cf;}
div div:nth-child(4) {background: #0b0;}
div div:nth-child(5) {background: #a6f;}
div div:nth-child(1) {flex: 1 0 0;}
div div:nth-child(2) {flex: 5 0 0;}
div div:nth-child(3) {flex: 0 1 50px;}
div div:nth-child(4) {flex: 0 5 100px;}
div div:nth-child(5) {flex: 0 0 50%;}
</style>
order 弹性项目顺序位置
order 样式属性是作用于弹性项目的样式属性,可以“改变弹性项目的位置”,属性值使用“无单位的整数”,默认值为 0,数字越小越靠近主轴起始点 ( Main Start ),下方的范例会改变原本 1~9 的顺序。
<!-- HTML 程式碼-->
<div class="f">
<div class="o3">1</div><div class="o4">2</div><div class="o1">3</div><div class="o5">4</div><div class="o2">5</div><div class="o9">6</div><div class="o8">7</div><div class="o7">8</div><div class="o6">9</div>
</div>
<!-- CSS 程式碼 -->
<style>
.f {
width: 300px;
height: 50px;
border: 1px solid #000;
display: flex;
font-size: 24px;
margin: 20px ;
}
div div {
padding: 5px 0px;
flex-grow: 1;
text-align: center;
}
div div:nth-child(1) {background: #f33;}
div div:nth-child(2) {background: #fb0;}
div div:nth-child(3) {background: #4cf;}
div div:nth-child(4) {background: #0b0;}
div div:nth-child(5) {background: #f9f;}
div div:nth-child(6) {background: #f80;}
div div:nth-child(7) {background: #6f6;}
div div:nth-child(8) {background: #ccc;}
div div:nth-child(9) {background: #ff0;}
.o1 {order: 1;}
.o2 {order: 2;}
.o3 {order: 3;}
.o4 {order: 4;}
.o5 {order: 5;}
.o6 {order: 6;}
.o7 {order: 7;}
.o8 {order: 8;}
.o9 {order: 9;}
</style>
使用 order 时需要注意,透过 CSS 选择器选取到的元素会被归类为“同一个顺序”,因此若选择了多个元素,这些元素会一起移动,下方范例会透过 CSS 选择器,将偶数元素的 order 设定为 2,将奇数元素的 order 设定为 3,就能让偶数放在前面,奇数放在后面。
<!-- HTML 程式碼-->
<div class="f">
<div>1</div><div>2</div><div>3</div><div>4</div><div>5</div><div>6</div><div>7</div><div>8</div><div>9</div>
</div>
<!-- CSS 程式碼 -->
<style>
.f {
width: 300px;
height: 50px;
border: 1px solid #000;
display: flex;
font-size: 24px;
margin: 20px ;
}
div div {
padding: 5px 0px;
flex-grow: 1;
text-align: center;
}
div div:nth-child(1) {background: #f33;}
div div:nth-child(2) {background: #fb0;}
div div:nth-child(3) {background: #4cf;}
div div:nth-child(4) {background: #0b0;}
div div:nth-child(5) {background: #f9f;}
div div:nth-child(6) {background: #f80;}
div div:nth-child(7) {background: #6f6;}
div div:nth-child(8) {background: #ccc;}
div div:nth-child(9) {background: #ff0;}
div div:nth-child(2n) {order: 2;}
div div:nth-child(2n-1) {order: 3;}
</style>
小结
这篇教学介绍的 flex、flex-grow、flex-shrink 和 flex-basis 是可以充分发挥 Flex 最大效益的样式属性,透过这些样式属性,就能产生自动适应不同父元素宽度的弹性项目,是相当方便好用的样式属性!
相关文章:认识弹性盒子 Flexbox、Flex 的对齐方式
微信扫码关注
抖音扫码关注