[教學]Flexbox
Flexbox就只是叫小朋友排好隊形而已
前言
前端在切版時最最需要的就是排版,上篇文章就有偷偷使用display: flex
來做排版,這次就讓我們來看看Flex到底有多麽強大!在了解Flex之前,我們需要知道它究竟是如何排版的。
以中央伍為準~~成體操隊形~~散開!
聽到這句口令,想必大家腦中已經浮現出排隊的隊形了吧!沒錯,這就是Flex的排版原理。想要叫人員乖乖排好就需要先限制場地,因此人員就只能在這個範圍活動,不會跑到外面去。而這個場地就是「外容器、Container、父元素」;而人員就是「內元件、items、子元素」,接下來大家就可以開始排排站好囉~~
*接下來我會以「Container」、「Items」來說明他們的關係
首先來看看Container、Items各自有哪些屬性:
Container:
Items:
Container
Flex主要都是在Container上下指令。
發動場地魔法卡「大地力量」,場面上地屬性怪獸的攻擊力可以上升500…
沒錯,可以把它想像成場地效果,你要裡面的東西怎樣他就會怎樣,這樣就可以很好的控制裡面的內容了。以下介紹的屬性都是放在Container裡面的喔。
Display
首先先宣告為flex
它才能使用。
Flex-direction
Flex-direction
負責管理Items該如何排列,它掌控著誰可以拿到主導權,能拿到主導權的有兩位人選,一位是column
,另一位是row
,也就是我們常講的「直行橫列」,直行是column
;橫列是row
。
所謂的主導權就是「主軸(main-axis)」,既然有主軸那就有「副軸(cross-axis)」。預設下主軸為row
,而副軸為column
。主副軸彼此的關係為「十字交叉」,若一方為主軸,則另一方就是副軸,但Flex-direction
只有決定主軸是誰,副軸的功用等等再說吧。我們現來看Flex-direction
,它有4個語法,分別是:
*因為瀏覽器對於每個語法的定義不同,因此在Chome上看到的flex-direction: column
、flex-direction: column-reverse
是會爆出框框的;而在Safari上看到的是塞好塞滿。不過兩者皆是把物件塞在同一排,即便有定義好Items的寬高,但在空間不夠時是會壓縮它們的喔!
咦咦咦!?我不要裡面的東西變形啦!!該怎麼解決呢?有兩個方法,第一個是減少Items,這樣空間就留出來了;第二個是加大Container的寬高。
但~~上面講的都治標不治本,接下來就來介紹解決方案吧!
Flex-wrap
Flex-wrap
決定了Items的排列方式,有別於前者說提到的Flex-direction
,它控制物件該不該「包起來」。我們知道單就下Flex-direction
只會讓items排一排站好,而且還有可能擠在一起,讓Items變形,因此Flex-wrap
透過包起來的方式,將塞不下的Items換行繼續塞,而換行的方向就是根據副軸去排的喔。說了這麼多我們直接看看它到底有哪些功能:
*Codepen展示中用到Flex-direction: row
,其餘的排列組合就請自己去玩玩探索吧!
*Flex-wrap: reverse
,反轉的地方是指「副軸反轉」,正常的方向是由左至右,由上至下,而反轉後的方向則變成了由右至左,由下至上
Flex-flow
那麼這個屬性又是幹嘛的呢??其實你也可以不用懂它,它就是Flex-direction
、Flex-wrap
的「組合技」,如此一來就可以共同定義主副軸的排列方式了。
*預設為flex-flow: row nowrap
接下來就進入重頭戲,也就是介紹Flex屬性是如何「排版」的吧!
Justify-content
Justify-content
定義了「主軸」的「對齊方式」,有以下5種方式:
*Codepen展示中用到Flex-flow: row wrap
,其餘的排列組合就請自己去玩玩探索吧!
*Justify-content
是「控制主軸」,不是「控制左右」。在Flex-direction
的控制下是有可能把主軸變為直向,副軸變為橫向。因此註解上我不以「靠左對齊」、「靠右對齊」而改用頭尾,原因是彼此的關係是互相的
*Justify-content:space-arounnd
與Justify-content:space-evenly
意思其實不太一樣喔。舉例來說每個items距離20px,那麼前者代表每個items都有20px,彼此的距離是40px;反觀後者,是每個items彼此之間的距離是20px
Align-items
Align-items
定義了「副軸」的「對其方式」,有以下5種方式:
*Codepen展示中用到Flex-flow: row wrap
、Justify-content: center
,其餘的排列組合就請自己去玩玩探索吧!
*使用stretch
時,請不要設死Items的高度喔,不然它會拉不開
Align-content
這個屬性是Align-items
的進階版,而且它跟Justify-content
長得有八成像,所以他們能控制的東西也是一樣差不多~這裡再再提醒一次:Justify-content
控制主軸;Align-content
控制副軸喔。
*Codepen展示中用到Flex-flow: row wrap
、Justify-content: center
,其餘的排列組合就請自己去玩玩探索吧!
*使用stretch
時,請不要設死Items的高度喔,不然它會拉不開
以上大致講完Container可以用的屬性了,那麼我們就,下面一位~~~~
Items
Items也是有很多東西可以控制的,它能做到的事情主要是items跟items之間的關係,像是誰在前誰在後的order
,又或是誰位置可以比較大誰位置可以比較小的Flex-grow
跟Flex-shrink
等等。有些屬性甚至能覆蓋掉Container的屬性呢,那就讓我們繼續看下去。
Order
order
屬性可以控制誰在前誰在後,即使在HTML上的物件是在最後一個,只要下達這個指令就可以輕輕鬆鬆要它在哪它就在哪囉。
*Codepen展示中用到Flex-flow: row wrap
、Justify-content: center
、Align-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
屬性決定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-items
、Align-content
一樣可以控制副軸的排列方式,它卻能更進一步個別調整單一item的排列方式,以下是它的語法:
*特別注意!Align-self
給定的值是會壓過Align-items
、Align-content
的喔
結語
其實Flex並沒有想象中的那麼難,我當初在學習時也是看到一大堆屬性就頭昏腦花了,但只要先了解Container與items各自是負責做什麼的,以及主軸和副軸之間的關係,其他的即便忘了,網路上找一下就知道該怎麼使用了。前端的路途是很遙遠的,我們共勉之~
參考資料:
CSS | 所以我說那個版能不能好切一點? - Flex 基本用法
[css] 搞懂 flex-grow, flex-shirk 及 flex-basis 三種屬性
圖片來源: