大頭照

你好,我是米米

菜雞前端工程師

[教學]Flexbox

Flexbox就只是叫小朋友排好隊形而已

米米

css

前言

前端在切版時最最需要的就是排版,上篇文章就有偷偷使用display: flex來做排版,這次就讓我們來看看Flex到底有多麽強大!在了解Flex之前,我們需要知道它究竟是如何排版的。

以中央伍為準~~成體操隊形~~散開!

聽到這句口令,想必大家腦中已經浮現出排隊的隊形了吧!沒錯,這就是Flex的排版原理。想要叫人員乖乖排好就需要先限制場地,因此人員就只能在這個範圍活動,不會跑到外面去。而這個場地就是「外容器、Container、父元素」;而人員就是「內元件、items、子元素」,接下來大家就可以開始排排站好囉~~

Container,Items

*接下來我會以「Container」、「Items」來說明他們的關係

首先來看看Container、Items各自有哪些屬性:

Container:

Items:

Container

Flex主要都是在Container上下指令。

發動場地魔法卡「大地力量」,場面上地屬性怪獸的攻擊力可以上升500…

沒錯,可以把它想像成場地效果,你要裡面的東西怎樣他就會怎樣,這樣就可以很好的控制裡面的內容了。以下介紹的屬性都是放在Container裡面的喔。

Display

首先先宣告為flex它才能使用。

Flex-direction

flex-direction

Flex-direction負責管理Items該如何排列,它掌控著誰可以拿到主導權,能拿到主導權的有兩位人選,一位是column,另一位是row,也就是我們常講的「直行橫列」,直行是column;橫列是row

所謂的主導權就是「主軸(main-axis)」,既然有主軸那就有「副軸(cross-axis)」。預設下主軸為row,而副軸為column。主副軸彼此的關係為「十字交叉」,若一方為主軸,則另一方就是副軸,但Flex-direction只有決定主軸是誰,副軸的功用等等再說吧。我們現來看Flex-direction,它有4個語法,分別是:

*因為瀏覽器對於每個語法的定義不同,因此在Chome上看到的flex-direction: columnflex-direction: column-reverse是會爆出框框的;而在Safari上看到的是塞好塞滿。不過兩者皆是把物件塞在同一排,即便有定義好Items的寬高,但在空間不夠時是會壓縮它們的喔!

咦咦咦!?我不要裡面的東西變形啦!!該怎麼解決呢?有兩個方法,第一個是減少Items,這樣空間就留出來了;第二個是加大Container的寬高。

但~~上面講的都治標不治本,接下來就來介紹解決方案吧!

Flex-wrap

flex-direction

Flex-wrap決定了Items的排列方式,有別於前者說提到的Flex-direction,它控制物件該不該「包起來」。我們知道單就下Flex-direction只會讓items排一排站好,而且還有可能擠在一起,讓Items變形,因此Flex-wrap透過包起來的方式,將塞不下的Items換行繼續塞,而換行的方向就是根據副軸去排的喔。說了這麼多我們直接看看它到底有哪些功能:

*Codepen展示中用到Flex-direction: row,其餘的排列組合就請自己去玩玩探索吧!

Flex-wrap: reverse,反轉的地方是指「副軸反轉」,正常的方向是由左至右,由上至下,而反轉後的方向則變成了由右至左,由下至上

Flex-flow

那麼這個屬性又是幹嘛的呢??其實你也可以不用懂它,它就是Flex-directionFlex-wrap的「組合技」,如此一來就可以共同定義主副軸的排列方式了。

*預設為flex-flow: row nowrap

接下來就進入重頭戲,也就是介紹Flex屬性是如何「排版」的吧!

Justify-content

justify-content

Justify-content定義了「主軸」的「對齊方式」,有以下5種方式:

*Codepen展示中用到Flex-flow: row wrap,其餘的排列組合就請自己去玩玩探索吧!

Justify-content是「控制主軸」,不是「控制左右」。在Flex-direction的控制下是有可能把主軸變為直向,副軸變為橫向。因此註解上我不以「靠左對齊」、「靠右對齊」而改用頭尾,原因是彼此的關係是互相的

Justify-content:space-arounndJustify-content:space-evenly意思其實不太一樣喔。舉例來說每個items距離20px,那麼前者代表每個items都有20px,彼此的距離是40px;反觀後者,是每個items彼此之間的距離是20px

Align-items

align-items

Align-items定義了「副軸」的「對其方式」,有以下5種方式:

*Codepen展示中用到Flex-flow: row wrapJustify-content: center,其餘的排列組合就請自己去玩玩探索吧!

*使用stretch時,請不要設死Items的高度喔,不然它會拉不開

Align-content

align-content

這個屬性是Align-items的進階版,而且它跟Justify-content長得有八成像,所以他們能控制的東西也是一樣差不多~這裡再再提醒一次:Justify-content控制主軸;Align-content控制副軸喔。

*Codepen展示中用到Flex-flow: row wrapJustify-content: center,其餘的排列組合就請自己去玩玩探索吧!

*使用stretch時,請不要設死Items的高度喔,不然它會拉不開

以上大致講完Container可以用的屬性了,那麼我們就,下面一位~~~~

Items

Items也是有很多東西可以控制的,它能做到的事情主要是items跟items之間的關係,像是誰在前誰在後的order,又或是誰位置可以比較大誰位置可以比較小的Flex-growFlex-shrink等等。有些屬性甚至能覆蓋掉Container的屬性呢,那就讓我們繼續看下去。

Order

order

order屬性可以控制誰在前誰在後,即使在HTML上的物件是在最後一個,只要下達這個指令就可以輕輕鬆鬆要它在哪它就在哪囉。

*Codepen展示中用到Flex-flow: row wrapJustify-content: centerAlign-content: space-around,其餘的排列組合就請自己去玩玩探索吧!

order預設為零,若要排在0前面的話也可以負值喔

Flex-basis

它決定了主軸上items的預設長度。以row當主軸來說它控制items的「寬度」;以column當主軸來說它控制items的「高度」

*範例當中Flex-basis的長度為50px。以row來當主軸的話所有items的「寬度」皆為50px;反之以column當主軸的話所有items的「高度」皆為50px

Flex-grow

flex-grow

這個屬性跟等一下講的屬性是相關的,可以將他們視為兄弟。Flex-grow屬性決定items如何分配剩餘空間。我們上範例會比較好理解:

第一個範例當中有三個items排在一起,彼此大小皆為100x100px。第二個範例只是都讓他們有flex-grow: 1的屬性,items就將Container撐好撐滿。

flex-grow的預設值為0,也可以給其他的值,這個值代表要將剩下的空間分成幾等分。以這題為例,Container:600x350px;box:100x100px,那麼剩餘的空間就是600-(100*3)=300,因此就要來瓜分剩餘的300。items有三個,每個都有flex-grow: 1,因此切為三等份,每等分的長度則為300/3=100,所以每個items都會獲得100px的長度。

那我們試著想一下,假設box1的flex-grow: 2,box2的flex-grow: 3那會變成怎麼樣呢?

剩餘空間300要分給5等分,每等分為60,其中box1占2等分所以是120,而box2占3等分所以是180。最終items的長度分別為:220px、280px、100px(若把codepen上的範例改成這題,他們的實際大小可能會有一點點的落差,因為items都有border,border的長度也是會被算在裡面的。)

Flex-shrink

剛剛的Flex-grow是處理當Container有剩餘空間時,將items「伸展」來符合Container的長度;現在Flex-shrink則是處理當Container不夠items塞時,將items「縮小」來符合Container的長度。

在第一個範例裡Container的大小是600x350px,每個items的長度皆為300px,照理來講items的長度比Container還要長,那為什麼它們沒有爆開呢?答案是在預設裡其實就已經加上了Flex-shrink:1了~因此它們都會被包在Container裡面。我們可以來算算實際上items到底多長,3個items總長度為3*300=900,扣掉Container的600,因此差為300。而各自的Flex-shrink皆為1,故300/3=100,每個items的長度都要減去100,所以長度為200。第二範例就只是把Flex-shrink設為0,items總長大於Container,那麼就會爆開了。

再來看看第三個範例,長寬依舊,但是Flex-shrink分別是2、3、1,故300/(2+3+1)=50。box1占了2份,300-(2*50)=200;box2占了3份,300-(3*50)=150;box3占了1份,300-(1*50)=250。這樣各位有清楚了嗎~

Align-self

align-self

終終終於來到最後一個屬性了啊!!!!(撒花~

這個屬性可以調整「副軸」的對齊屬性,再重申一次,是「副軸」喔不是主軸。它與Align-itemsAlign-content一樣可以控制副軸的排列方式,它卻能更進一步個別調整單一item的排列方式,以下是它的語法:

*特別注意!Align-self給定的值是會壓過Align-itemsAlign-content的喔

結語

其實Flex並沒有想象中的那麼難,我當初在學習時也是看到一大堆屬性就頭昏腦花了,但只要先了解Container與items各自是負責做什麼的,以及主軸和副軸之間的關係,其他的即便忘了,網路上找一下就知道該怎麼使用了。前端的路途是很遙遠的,我們共勉之~


參考資料:

圖解:CSS Flex 屬性一點也不難

CSS | 所以我說那個版能不能好切一點? - Flex 基本用法

[css] 搞懂 flex-grow, flex-shirk 及 flex-basis 三種屬性

CSS Flexbox

圖片來源:

A Complete Guide to Flexbox

感謝抖內

BUY ME A COFFEE
comments powered by Disqus
comments powered by Disqus

advertisement

recent post

categories

advertisement

about

你好,我是米米,是個剛畢業就已經成為社畜的前端工程師==