Flexbox 弹性盒子
Flex 弹性排版是近几年网页设计常用的排版方式,构成 Flex 弹性排版的网页元素就称为“弹性盒子 Flexbox”,Flexbox 不需要额外设定,就具有自动对齐和调整宽高的能力,是相当好用的网页元素!这篇教学会介绍什么是 Flexbox,以及最基本的 flex-direction、flex-wrap 和 flex-flow 样式属性。
相关文章:Flex 的对齐方式、Flex 的弹性伸缩
快速导览:
认识弹性盒子 Flexbox
当元素的 display 显示类型设定为 flex 或 inline-flex 时,该元素就变成了“弹性容器 Flex container”,这个元素里的所有子元素都会变成“弹性项目 Flex item”,而 Flexbox 就是这一整组弹性容器与弹性项目,就会统称为“弹性盒子 Flexbox”,透过 Flexbox 进行排版,也就可称之为“Flex 弹性排版”。弹性容器与项目有各自的显示类型,相关说明如下:
| 弹性盒子 | 元素 | 说明 |
|---|---|---|
| 弹性容器 | 设定 flex 的元素 |
表现和 block 相同,强制换行。 |
| 弹性容器 | 设定 inline-flex 的元素 |
表现和 inline-block 相同,不换行。 |
| 弹性项目 | 子元素 | 按照弹性容器的设定,决定对齐和换行的方式。 |
CSS 有专门针对 Flex 的样式属性,这些样式属性只有在 Flex 容器或项目才会作用 ( 部分通用于显示类型为 Gird 元素 ),下方列出相关样式属性:
| Flex 相关样式属性 | 说明 | 作用元素 |
|---|---|---|
| flex-direction | 弹性元素方向 | 弹性容器 |
| flex-wrap | 弹性元素换行 | 弹性容器 |
| flex-flow | 弹行元素方向缩写格式 | 弹性容器 |
| row-gap | 弹行元素垂直间距 | 弹性容器 |
| column-gap | 弹行元素水平间距 | 弹性容器 |
| gap | 弹行元素间距缩写格式 | 弹性容器 |
| justify-content | 水平对齐 | 弹性容器 |
| align-items | 单行垂直对齐 | 弹性容器 |
| align-content | 多行垂直对齐 | 弹性容器 |
| align-self | 覆写单一元素垂直对齐方式 | 弹性项目 |
| flex-grow | 弹性项目“扩展”比例 | 弹性项目 |
| flex-shrink | 弹性项目“缩小”比例 | 弹性项目 |
| flex-basis | 弹性项目“基础”比例 | 弹性项目 |
| flex | 弹性伸缩缩写格式 | 弹性项目 |
| order | 弹性项目顺序位置 | 弹性项目 |
下方范例将 span 元素变成 flex 和 inline-flex 两种弹性盒子,因为显示类型类似 block 或 inline-block,所以可以调整宽高,flex 的元素也会强制换行。
<!-- HTML 程式碼-->
<span>apple</span>
<span>oxxo</span>
<span>banana</span>
<span>coconut</span>
<span class="f">apple</span>
<span class="f">oxxo</span>
<span class="f">banana</span>
<span class="f">coconut</span>
<span class="fb">apple</span>
<span class="fb">oxxo</span>
<span class="fb">banana</span>
<span class="fb">coconut</span>
<!-- CSS 程式碼 -->
<style>
body {padding: 10px; }
span {
background: #f509;
margin: 10px;
height: 50px;
}
.f {
display: inline-flex; /* class 為 f 的元素是 inline-flex */
background: #0c09;
}
.fb {
display: flex; /* class 為 fb 的元素是 flex */
background: #0c09;
}
</style>
下方范例将 span 元素变成弹性盒子,可以发现内容的 strong 和 em 元素都变成弹性项目,不仅不会换行,也不会因为换行导致背景或边框重叠的状况 ( 参考“文字行高、文字缩排” )。
<!-- HTML 程式碼-->
<span><strong>apple</strong> <em>banana</em> <em>orange</em></span>
<span class="f"><strong>apple</strong> <em>banana</em> <em>orange</em></span>
<span><strong>An apple a day keeps the doctor away!!</strong> <em>Hello World! I am oxxo.studio!!</em></span>
<span class="f"><strong>An apple a day keeps the doctor away!!</strong> <em>Hello World! I am oxxo.studio!!</em></span>
<!-- CSS 程式碼 -->
<style>
body {padding: 10px;}
span {
border: 1px solid #000;
margin: 10px;
padding: 5px;
}
strong, em {
background: #f509;
margin: 5px;
}
.f {display: flex;} /* class 為 f 的元素是 flex 元素 */
.f * {background: #0c09;} /* flex 元素的子元素背景都是綠色 */
</style>
下方范例将 div 元素变成弹性盒子,可以发现内容的 div、strong 和 em 元素都变成弹性项目,不仅不会换行,也不会因为换行导致背景或边框重叠的状况。
<!-- HTML 程式碼-->
<div><div>apple</div> <div>banana</div> <div>orange</div></div>
<div class="f"><div>apple</div> <div>banana</div> <div>orange</div></div>
<div><strong>An apple a day keeps the doctor away!!</strong> <em>Hello World! I am oxxo.studio!!</em></div>
<div class="f"><strong>An apple a day keeps the doctor away!!</strong> <em>Hello World! I am oxxo.studio!!</em></div>
<!-- CSS 程式碼 -->
<style>
body {padding: 10px;}
div {
border: 1px solid #000;
margin: 10px;
padding: 5px;
}
div * {
border: none;
background: #f509;
margin: 5px;
}
.f {display: flex;} /* class 為 f 的元素是 flex 元素 */
.f * {background: #0c09;} /* flex 元素的子元素背景都是綠色 */
</style>
flex-direction 弹性元素方向
当元素变弹性盒子之后,就会采用“轴向”作为排版布局的方式,而不是使用传统常见的 inline 或 block 进行排版,flex 元素的轴向分成“主轴 Main axis”和“交叉轴 Cross axis”,两条轴线呈垂直状态,子元素会根据“主轴的方向”进行排列 ( 从起点 main start 出发往结束点 main end 的方向 )。
主轴通常表示“水平方向”,交叉轴通常表示“垂直方向”。
flex-direction 样式属性表示主轴 main axis 的方向,也就是子元素排列的方向,没有继承特性,共有下列几种属性值:
| 属性值 | 说明 |
|---|---|
| row | 左到右 ( 默认值 ) |
| row-reverse | 右到左 |
| column | 上到下 |
| column-reverse | 下到上 |
下方范例使用四个变成 flex 弹性容器的 div,分别呈现四种不同的弹性项目排列方向。
<!-- HTML 程式碼-->
<div class="f a"><div>1</div><div>2</div><div>3</div><div>4</div><div>5</div></div>
<div class="f b"><div>1</div><div>2</div><div>3</div><div>4</div><div>5</div></div>
<div class="f c"><div>1</div><div>2</div><div>3</div><div>4</div><div>5</div></div>
<div class="f d"><div>1</div><div>2</div><div>3</div><div>4</div><div>5</div></div>
<!-- CSS 程式碼 -->
<style>
.f {
display: flex; /* 設定為彈性容器 */
border: 1px solid #000;
font-family: monospace;
font-size: 20px;
margin: 5px;
width: 200px;
height: 200px;
}
.a {flex-direction: row;} /* 左到右 */
.b {flex-direction: row-reverse;} /* 右到左 */
.c {flex-direction: column;} /* 上到下 */
.d {flex-direction: column-reverse;} /* 下到上 */
div div {
text-align: center;
width: 30px;
height: 30px;
margin: 2px;
}
div div:nth-child(1) {background: #f90;}
div div:nth-child(2) {background: #f66;}
div div:nth-child(3) {background: #4d4;}
div div:nth-child(4) {background: #4bf;}
div div:nth-child(5) {background: #f9f;}
</style>
如果同时使用 writing-mode:rl 或 writing-mode:lr,会造成轴向反转,呈现出不同方向的排列效果 ( 参考 writing-mode 书写模式 )。
<!-- HTML 程式碼-->
<div class="f a"><div>1</div><div>2</div><div>3</div><div>4</div><div>5</div></div>
<div class="f b"><div>1</div><div>2</div><div>3</div><div>4</div><div>5</div></div>
<div class="f c"><div>1</div><div>2</div><div>3</div><div>4</div><div>5</div></div>
<div class="f d"><div>1</div><div>2</div><div>3</div><div>4</div><div>5</div></div>
<div class="f r a"><div>1</div><div>2</div><div>3</div><div>4</div><div>5</div></div>
<div class="f r b"><div>1</div><div>2</div><div>3</div><div>4</div><div>5</div></div>
<div class="f r c"><div>1</div><div>2</div><div>3</div><div>4</div><div>5</div></div>
<div class="f r d"><div>1</div><div>2</div><div>3</div><div>4</div><div>5</div></div>
<!-- CSS 程式碼 -->
<style>
.f {
display: flex;
border: 1px solid #000;
font-family: monospace;
font-size: 20px;
margin: 5px;
width: 200px;
height: 200px;
writing-mode:vertical-rl; /* 設定書寫方向 */
float: left;
}
.f.r {
writing-mode:vertical-lr; /* 設定書寫方向 */
}
.a {flex-direction:row;}
.b {flex-direction:row-reverse;}
.c {flex-direction:column;}
.d {flex-direction:column-reverse;}
div div {
text-align: center;
width: 30px;
height: 30px;
margin: 2px;
}
div div:nth-child(1) {background: #f90;}
div div:nth-child(2) {background: #f66;}
div div:nth-child(3) {background: #4d4;}
div div:nth-child(4) {background: #4bf;}
div div:nth-child(5) {background: #f9f;}
</style>
flex-wrap 弹性元素换行
当弹性容器的宽度无法容纳弹性项目时,弹性项目在默认的状态下仍然会保持“自动分配宽度”且“不换行”,如果最后宽度不足就会超过容器范围,而 flex-wrap 样式属性可以控制弹性项目的换行行为,没有继承特性,相关属性值如下:
| 属性值 | 说明 |
|---|---|
| nowrap | 弹性项目维持一行,不换行,可能会溢出父元素宽度 ( 默认值 )。 |
| wrap | 允许多行,换行后出现在原行之前。 |
| wrap-reverse | 许多行,换行后出现在原行之后,类似 cross axis 反转。 |
下方使用两组范例,第一组的三个 div 使用默认 flex-direction 样式,搭配九个弹性项目呈现不同的换行效果,第二组的三个 div 使用 flex-direction:column-reverse;,呈现不同轴向换行的效果。
<!-- HTML 程式碼-->
<div class="f a"><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>
<div class="f b"><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>
<div class="f c"><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>
<div class="f cr a"><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>
<div class="f cr b"><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>
<div class="f cr c"><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 {
display: flex;
border: 1px solid #000;
font-family: monospace;
font-size: 20px;
margin: 40px 10px;
width: 200px;
height: 200px;
float: left;
}
.a {flex-wrap: nowrap;}
.b {flex-wrap: wrap;}
.c {flex-wrap: wrap-reverse;}
.cr {flex-direction: column-reverse;} /* class 為 cr 的為 column-reverse */
div div {
text-align: center;
width: 30px;
height: 30px;
margin: 2px;
}
div div:nth-child(1) {background: #f90;}
div div:nth-child(2) {background: #f66;}
div div:nth-child(3) {background: #4d4;}
div div:nth-child(4) {background: #4bf;}
div div:nth-child(5) {background: #f9f;}
div div:nth-child(6) {background: #fc0;}
div div:nth-child(7) {background: #0b5;}
div div:nth-child(8) {background: #0df;}
div div:nth-child(9) {background: #aaa;}
</style>
flex-flow 弹行元素方向缩写样式
flex-flow 样式属性其实只是 flex-direction 和 flex-wrap 的“缩写样式”,没有继承特性,具有两个属性值,分别是 flex-direction 和 flex-wrap 的属性值 ( 位置可颠倒 ),初始值为“row nowrap”,如果只输入一个属性值,另外一个属性值就会带入默认值。
下方的范例分别展示“单一属性值”、“两个属性值”、“两个属性值位置颠倒”的呈现方式。
<!-- HTML 程式碼-->
<div class="f a"><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>
<div class="f b"><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>
<div class="f c"><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>
<div class="f d"><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 {
display: flex;
border: 1px solid #000;
font-family: monospace;
font-size: 20px;
margin: 20px 10px;
width: 200px;
height: 200px;
float: left;
}
.a {flex-flow: wrap;} /* 單一屬性值 */
.b {flex-flow: row wrap;} /* 兩個屬性值,等於上方效果 */
.c {flex-flow: column-reverse wrap-reverse;} /* 兩個屬性值 */
.d {flex-flow: wrap-reverse column-reverse;} /* 兩個屬性值位置顛倒,等於上方效果 */
div div {
text-align: center;
width: 30px;
height: 30px;
margin: 2px;
}
div div:nth-child(1) {background: #f90;}
div div:nth-child(2) {background: #f66;}
div div:nth-child(3) {background: #4d4;}
div div:nth-child(4) {background: #4bf;}
div div:nth-child(5) {background: #f9f;}
div div:nth-child(6) {background: #fc0;}
div div:nth-child(7) {background: #0b5;}
div div:nth-child(8) {background: #0df;}
div div:nth-child(9) {background: #aaa;}
</style>
row-gap、column-gap、gap 弹性元素间距
前几个范例都是使用 margin 控制元素间距,而 CSS 也有提供专门控制间距的样式属性 row-gap、column-gap 和 gap,这三个样式都是使用“长度单位”数字,且没有继承特性,因为弹性元素会自动计算的换行间距,所以弹性元素间距并非换行间距,而是水平或垂直排列的间隔,相关说明如下:
这三个样式属性也可作用于 Grid 网格元素,参考:row-gap、column-gap、gap 网格间距
| 样式属性 | 说明 |
|---|---|
row-gap |
弹性元素垂直排列时每个元素的间距。 |
column-gap |
弹性元素水平排列时每个元素的间距。 |
gap |
使用两个数值同时设定垂直和水平的间距,写法 (垂直 水平),如果只有一个数值表示垂直和水平使用相同数值。 |
下方范例使用七个不设定宽高的弹性元素,因为没有设定宽高,默认状态会像第一个 div 没有间距的水平派列,如果有设定 column-gap 或 gap 里的水平间距,水平排列的弹性元素就会出现水平间距,换行后并不会出现垂直间距,如果有设定 row-gap 或 gap 里的垂直间距,垂直排列的弹性元素就会出现垂直间距,换行后并不会出现水平间距。
<!-- HTML 程式碼-->
<h3>預設狀態</h3>
<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>
<h3>水平排列</h3>
<div class="f a"><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>
<div class="f b"><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>
<div class="f c"><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>
<h3>垂直排列</h3>
<div class="f cr a"><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>
<div class="f cr b"><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>
<div class="f cr c"><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>
h3 {
clear: both;
margin: 10px 10px 0;
}
.f {
display: flex;
border: 1px solid #000;
margin: 10px 10px 40px;
width: 120px;
height: 120px;
float: left;
flex-wrap: wrap; /* 允許多行,換行後出現在原行之前 */
}
.cr {flex-direction: column-reverse;} /* class 為 cr 的為 column-reverse */
.a {row-gap:10px; } /* 垂直間距 */
.b {column-gap:10px;} /* 水平間距 */
.c {gap: 5px 20px;} /* 垂直間距 5px,水平間距 20px */
div div {text-align: center;}
div div:nth-child(1) {background: #f90;}
div div:nth-child(2) {background: #f66;}
div div:nth-child(3) {background: #4d4;}
div div:nth-child(4) {background: #4bf;}
div div:nth-child(5) {background: #f9f;}
div div:nth-child(6) {background: #fc0;}
div div:nth-child(7) {background: #0b5;}
div div:nth-child(8) {background: #0df;}
div div:nth-child(9) {background: #aaa;}
</style>
小结
弹性盒子 Flexbox 的排版方式,是目前网页设计师爱用的排版技巧,可以用更简单的 HTML 和 CSS 程序码,做出更多灵活弹性的版面,大家不妨开始在自己的网页中使用 Flex 吧!
相关文章:Flex 的对齐方式、Flex 的弹性伸缩
微信扫码关注
抖音扫码关注