認識彈性盒子 Flexbox
Flex 彈性排版是近幾年網頁設計常用的排版方式,構成彈性排版的網頁元素就稱為「彈性盒子 Flexbox」,Flexbox 不需要額外設定,就具有自動對齊和調整寬高的能力,是相當好用的網頁元素!這篇教學會介紹什麼是 Flexbox,以及最基本的 flex-direction、flex-wrap 和 flex-flow 樣式屬性。
快速導覽:
認識彈性盒子 Flexbox
當元素的 display
顯示類型設定為 flex
或 inline-flex
時,該元素就變成了「彈性容器 Flex container」,這個元素裡的所有子元素都會變成「彈性項目 Flex item」,而 Flexbox 就是這一整組彈性容器與彈性項目,就會統稱為「彈性盒子 Flexbox」,透過 Flexbox 進行排版,也就可稱之為「Flexbox 彈性排版」。彈性容器與項目有各自的顯示類型,相關說明如下:
彈性盒子 | 元素 | 說明 |
---|---|---|
彈性容器 | 設定 flex 的元素 |
表現和 block 相同,強制換行。 |
彈性容器 | 設定 inline-flex 的元素 |
表現和 inline-block 相同,不換行。 |
彈性項目 | 子元素 | 按照彈性容器的設定,決定對齊和換行的方式。 |
下方範例將 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>
Flexbox 相關樣式屬性
CSS 有專門針對 Flexbox 的樣式屬性,這些樣式屬性只有在 Flexbox 容器或項目才會作用 ( 部分通用於顯示類型為 Gird 元素 ),下方列出 Flexbox 相關樣式屬性:
Flexbox 相關樣式屬性 | 說明 | 作用元素 |
---|---|---|
flex-direction | 彈性元素方向 | 彈性容器 |
flex-wrap | 彈性元素換行 | 彈性容器 |
flex-flow | 彈行元素方向縮寫樣式 | 彈性容器 |
justify-content | 水平對齊 | 彈性容器 |
align-items | 單行垂直對齊 | 彈性容器 |
align-content | 多行垂直對齊 | 彈性容器 |
align-self | 覆寫單一元素垂直對齊方式 | 彈性項目 |
flex-grow | 彈性項目「擴展」比例 | 彈性項目 |
flex-shrink | 彈性項目「縮小」比例 | 彈性項目 |
flex-basis | 彈性項目「基礎」比例 | 彈性項目 |
flex | 彈性伸縮樣式縮寫 | 彈性項目 |
order | 彈性項目順序位置 | 彈性項目 |
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
樣式屬性可以控制彈性項目的換行行為,沒有繼承特性,相關屬性值如下:
屬性值 | 說明 |
---|---|
norwap | 彈性項目維持一行,不換行,可能會溢出父元素寬度 ( 預設值 )。 |
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>
小結
彈性盒子 Flexbox 的排版方式,是目前網頁設計師愛用的排版技巧,可以用更簡單的 HTML 和 CSS 程式碼,做出更多靈活彈性的版面,大家不妨開始在自己的網頁中使用 Flexbox 吧!
意見回饋
如果有任何建議或問題,可傳送「意見表單」給我,謝謝~