CSS Flex & Grid 排版詳解(上):What the Flex?


Posted by Nicolakacha on 2020-09-20

為什麼要用 Flex 和 Grid?

在 Flex 出現以前,CSS 撰寫人員過往常利用 Float 來排版,然而 Float 排版最大的缺點是它對於元素之間的連結很薄弱。

例如排在一起的元素之不知道彼此的寬度,需仰賴開發人員事先算好,假設算好兩個區塊各佔 30% 和 70%,任一元素只要增加 1 pixel 就會破版。

又或著是當子元素有了 float 的屬性,父元不知道子元素多高,也就無法撐開來以包裹子元素,必須得做清除浮動才可以。

Float 排版的缺點還有很難做到讓左右兩個區塊等高,以及垂直置中設定不易等。所以我們就有了 Flex 和 Grid 這些新的 layout model 工具來幫忙啦。

本篇會先介紹 Flex 排版,Grid 排版則會在下篇介紹。

What The Flex?

啟用方式:

只要加上 display: flex 之後,該元素的子元素都會變成 flex 元素。

.container {
    display: flex
}


資料的流向:flex-direction

flex 子元素的方向,也就是資料的流向,我們稱為主軸方向,而與主軸垂直的軸則是交叉軸。透過 給 flex 容器設定 flex-direction 即可調整主軸方向,預設的是 row,也就是由左往右排,而 column 則是由上往下排,若加上 -reverse 則倒轉過來的意思。

之後其他 flex 的屬性會在用到主軸、交叉軸的概念,所以如果搞混或是忘了哪個是主軸的時候,可以看一下自己的資料流向,來重新回憶起哪個是主軸。

flex-direction: row

flex-direction: row-reverse

flex-direction: column

flex-direction: column-reverse


要不要換行:flex-wrap

flex 子元素預設會填滿主軸的寬度,而不會自動換行,如果為每個子元素設定同樣的寬度,子元素會嘗試看看能不能做到設定的寬度,若不能,就會不管我們設定的寬度而繼續留在同一行上,這是因為 flex 容器預設的 flex-wrap 屬性是 nowrap,如果改設定成 wrap,就會往下換行。而設定 wrap-reverse 則會往上換行。

flex-wrap: nowrap

flex-wrap: wrap

flex-wrap: wrap-reverse


元素的順序:order

想要調整 flex 子元素的位置順序,我們可以利用 order 屬性。order 的值越小則順序越前面,order 的預設值是 0,若想把某個元素直接拉到最前面,也可以直接設定成 -1,反之,想把某個元素挪到最後面,可以直接設定成 1 。

將第五個子元素加上 order: -1 移到最前面:

將第一個子元素加上 order: 1 移到最後面:


在主軸上怎麼排:justify-content

justify-content 這個屬性是使用在 flex 容器上,用來定義 flex 子元素怎麼在主軸上面排列,在使用 justify-content 的時候要時刻記住自己的主軸在哪裡,才不會亂掉,以下的範例都是主軸預設是 row 的情況下的排列情形。

justify-content: flex-start:這是 justify-content 屬性的預設值,意思就是把 flex 子元素從主軸開始一個個接著排:

justify-content: flex-end:則是把 flex 子元素的尾端貼著主軸尾端排好:

justify-content: center:是把所有 flex 子元素集中在主軸中間排好,把多餘的空間平分在主軸兩側:

justify-content: space-between:把多餘的空間平分在每個 flex 子元素之間:

justify-content: space-around:除了把多餘的空間分配給每個 flex 子元素之間外,整個資料流的主軸兩側也分配空間:

justify-content: space-evenly:每兩個 flex 物件之間的空間都相等:

要特別注意 space-around 和 space-evenly 的差異:


在交叉軸上怎麼排:align-items

align-items 也是使用在 flex 容器上,來定義 flex 子元素怎麼在交叉軸上面排列,align-items 的預設值是 stretch,flex 子元素會直接延展開來填滿容器(但仍會被 min/max-width 規範)。下列範例是預設主軸是 row 的情況。

align-items: stretch 這是 align-items 屬性的預設值,會在交叉軸上延展開來填滿容器:

align-items: flex-start 從交叉軸的起點開始排:

align-items: flex-end 從交叉軸的終點開始排:

align-items: center 排在交叉軸的中間:

align-items: baseline 以 flex 子元素的底線對齊:


在交叉軸上分配多餘空間:align-content

align-content 用來定義如何分配交叉軸上多行之間的多餘空間,也就是說 align-content 只在 flex 子元素的排列在 flex 容器中「不只一行的時候」有作用,如果我們的子元素都在同一行上,當然就沒有怎麼分配「多行之間的剩餘空間」的問題。

align-content: stretch align-content 的預設值是 stretch,也就是每行自動在交叉軸上延展並填滿容器:

align-content: flex-start 把多行之間全部的多餘空間都往交叉軸的尾端丟,讓 flex 子元素們都黏在一起,中間沒有空間:

align-content: flex-end 把多行之間全部的多餘空間都往交叉軸的起點丟,讓 flex 子元素們都黏在一起,中間沒有空間:

align-content: center 把多行之間的多餘空間分配到交叉軸的起點和終點,讓 flex 子元素排在中間黏在一起:

align-content: space-between 把多行之間的多餘空間分配都所有 flex 子元素之間:

align-content: space-around 把多餘的空間均分在每個 flex 元素之間,但交叉軸的起點和終點只各分一半(圖中的容器有 padding):

align-content: space-evenly 交叉軸上每兩個 flex 元素之間的空間是完全相同的(圖中的容器有 padding):


個別 flex 子元素在交叉軸的排列 align-self

用來定義單個 flex 子元素怎麼在交叉軸上排列,可以當成用來為某個 flex 子元素壓過預設的交叉軸排列效果的屬性。能使用的值和 align-items 一樣。

align-self: flex-start

align-self: flex-end

align-self: center

align-self: baseline

align-self: stretch


細微調整 flex 子元素的空間分配:flex: <flex-grow> <flex-shrink> <flex-basis>

透過在 flex 子元素上設定 flex 屬性,可以調整 flex 子元素的伸展比(flex-grow)、壓縮比(flex-shrink)以及基本比(flex-basis )。如果當 flex 只填了一個值,則代表是伸展比,若填三個值,則依序代表身沾比、壓縮比及基本比。

flex-grow:伸展比
當有剩餘空間時,要怎麼把剩餘空間分配給同條主軸線上每個元素。flex-grow 預設值為 0,未進行設定時,不會將剩餘空間分配給子元素做長度「伸展」。

舉例來說,如果每個 flex 子元素都設定 flex-grow: 1,剩餘的空間會等分給每個 flex 子元素,如果其中一個子元素設定 flex-grow: 2,則會試著給該元素分配兩單位的「多餘空間」。
picture from CSS-TRICKS

flex-shrink:壓縮比
壓縮比的用處是,如有必要的時候,該子元素要放棄多少的空間以壓縮自身,尚未進行設定時預設值為 1,若有設定時,會按照數字壓縮比例分配。設定為 0 則代表不被壓縮。

flex-basis:基本比
子元素在分配任何多餘空間時的預設大小,可以是百分比,也可以是一般的寬度單位。基本比的預設值為 auto,當設定為 auto 時,則基本比依據物件本身的寬或高,若設定為 content,則是依據該物件的內容。

舉例來說,

.box1 {
  flex: 1 100px;
}
.box2 {
 flex: 1 0 100px;
}

當容器寬度足夠的時候,box1 伸展成 box2 的兩倍:

當容器寬度不足的時候,box 2 不壓縮,為了維持 box2 的寬度,box1 就會被壓縮變窄:


增加 flex 的瀏覽器支援性

使用瀏覽器擎前綴(Vendor prefix)引來增加 flex 屬性的瀏覽器支援性,利用像是 Autoprefixer 的工具可以幫我們的 CSS 自動加上這些 prefix。也可以使用 Gulp 的 Autoprefixer 套件來完成。

總結

以上就是 Flex 排版各種屬性的用法啦,Flex 解決了過往 Float 排版時各元素缺乏連結的問題,也讓我們更容易做到一些符合響應式設計的網站排版,這裡再列出兩個 flex 小遊戲給大家多多練習,還有一些我自己在理解 flex 排版時找到覺得非常棒的資源和文章:
Flexbox Defense
FLEXBOX FROGGY
Samanthaming 上的 flexbox 30 系列文
CSS-Tricks 上的 Flex 教學文章
Wes Bos 免費 Flex 教學課程:What The Flexbox?! by Wes Bos

但有了 Flex 這麼好用的工具,為什麼還需要 Grid 呢?接著下篇我們來看看更潮的(?) Grid 排版吧!


#flex #Flexbox







Related Posts

How to Set Up Firewall with UFW on Ubuntu 20.04

How to Set Up Firewall with UFW on Ubuntu 20.04

Build an AI Line Chatbot using AWS Bedrock

Build an AI Line Chatbot using AWS Bedrock

部署 React App

部署 React App


Comments