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

Angular 9 + Firebase (2) : Firebase Authentication 做個 Google 登入應用

Angular 9 + Firebase (2) : Firebase Authentication 做個 Google 登入應用

Day05 - CSS色彩、背景與漸層

Day05 - CSS色彩、背景與漸層

瀏覽器的事件傳遞機制

瀏覽器的事件傳遞機制


Comments