簡單介紹
雖然說 Flexbox 已經推出好一段時間了,但說實在話我自己好像沒有特別著墨。當然,我覺得如果可以的話,去看一下 Amos 的課程,一定比看我在這邊講幹話來得實際!
首先,我們先理解一下 flex
的作法,
.flexbox {
display: flex;
}
首先是把一個 DOM 元件定義成 flex
,這樣接下來的設計才會生效。這個 flex
元件預設會使用 row
這個維度來顯示資料。換句話說,你若什麼都不寫的話,他的 flex-flow
預設就會是 row nowrap
這樣的設定,
.flexbox {
display: flex;
flex-flow: row nowrap;
}
如果我們有一個 HTML 長這樣,
<main>
<section class="flexbox">
<h1 class="slogan">Hello World</h1>
<h4 class="description">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed sed eleifend dui. Ut ac justo eu orci hendrerit tempus.</h4>
<picture class="picture">
<source srcset="./static/hero.avif,
./static/[email protected] 2x,
./static/[email protected] 3x">
<source srcset="./static/hero.webp,
./static/[email protected] 2x,
./static/[email protected] 3x">
<img srcset="./static/hero.png,
./static/[email protected] 2x,
./static/[email protected] 3x"
src="./static/hero.png"
alt="Hello World">
</picture>
</section>
</main>
那麼你會發現三個元素都擠在一起,而且會超出畫面。
這個時候你想說,我在 .flexbox
加上寬度限制應該就可以了吧?
.flexbox {
display: flex;
width: 100%;
}
這樣沒用喔~
如果加上 overflow: hidden
呢?他就會變成畫面被切掉的樣子。
那我要平均一下,這樣我可以在裡面的元件使用如下的設定,
.slogan, .description, .picture {
flex: 0 1 33.33%;
}
你以為圖片會縮小嗎?這樣沒用喔~
接著你必須針對圖片的最大寬度做設定,
.picture img {
max-width: 100%;
}
最終會呈現的樣子是這樣,
好的,現在來說明一下這樣的設定最終會影響到的地方,
flex
是語法糖,三個數值分別為flex-grow
,flex-shrink
,flex-basis
。- 上述三個預設值分別為
0
,1
,auto
,翻成中文就是不分配剩餘空間,空間不足可壓縮,自動指定寬度。 .slogan
,.description
,.picture
會被定義成display: block;
的元件。- 在裡面用
float
是無效的。 - 在裡面用
position: absolute
,position: fixed
請左轉離開謝謝。
所以如果我想要圖片比較大,
.slogan, .description, .picture {
flex: 0 1 33.33%;
}
.picture {
flex: 1 0 auto;
}
這樣你的圖片就會填滿所分配到的空間。但,請切記,這個時候 flex-basis
所分配的空間就不會是原本的 33.33%
了。然後,你會發現你的圖片又超出畫面的範圍了。
所以,在這個時候你需要把 flex-shrink
設定為 1
,這樣你的圖片才不會被切掉。
好了,這邊就有幾個癥結點需要留意,
flex-basis
會覆蓋原有的width
設定(包含auto
)。flex-grow
跟flex-basis
同時設定,後者會被覆蓋寬度效果。flex-grow
若為0
則flex-basis
會恢復效果。flex-sharink
若為0
,flex-basis
若為auto
,內容會撐滿整個元件(甚至溢出容器)。
你的外層容器若為相對寬度,且為不斷行(nowrap
),則請留意以下狀況,
flex-basis
設定為絕對數值(例如600px
)無效果。flex-basis
若有值,flex-grow
設定1
以上無效。flex-basis
若無值,flex-sharink
設定1
以上無效。flex-basis
總和大於外層容器,flex-sharink
數值越大,縮小幅度越多。
以上各種情況,希望大家不會遇到。
行與列
剛剛提到的都是以「列」的方式來呈現,當然 flex
也可以使用「行」的方式呈現,
.flexbox {
display: flex;
flex-flow: column nowrap;
}
這樣的使用情境並不多,由於我們習慣了多欄方式來排列畫面,所以使用列來排列的地方就不是那麼廣泛。通常,會使用這種方式排列,以整個網站結構來看,天地之間講幹話就是,
<body>
<header><!-- 天 --></header>
<main><!-- 講幹話 --></main>
<footer><!-- 地 --></footer>
</body>
如果我們把 <body>
當作是一個最大的 flex
容器來看,裡面的 <header>
, <main>
與 <footer>
就是「行」排序的方式。
請不要真的把
<body>
設定為flex
。
然而,關於 column
這件事情,大抵上跟 row
沒有太多差異,唯一比較不一樣的地方,在於 wrap
這件事情上。
可以參考我 比較近期 的幹話文章。
實際使用上,他對於卡片式的排版還是有所幫助的,只要你的卡片高度固定,這個排版方式使用起來會比較方便。
那個斷點
客戶說我這個斷行是看過八字的。
首先,如果你在 flex-wrap
設定了 wrap
或是 wrap-reverse
的話,當寬度不足的時候,就會出現斷點。最簡單的例子就是,
.slogan, .description, .picture {
flex: 1 0 50%;
}
然後 .picture
就一定會被中斷放到下一列。換句話說,就是當 flex-basis
填滿了容器的寬度的時候,如果有發生「不足」的情況,就會將「下一個」元件給斷行。然而,這個斷行的設定,會干擾到某些東西,當你的容器使用相對寬度的時候,會發生這些事情,
flex-sharink
在斷行設定下無效果。flex-basis
若在一行內「未填滿」,則flex-grow
會影響元件相對寬度。- 若元件的
flex-basis
相加剛好填滿一行,則flex-grow
無效果。 - 「被斷行」的元件若
flex-grow
大於等於1
,會無視flex-basis
填滿容器。
我個人是覺得,應該不會有人會著墨在 flex
這件事情上打轉,頂多就是打開 Bootstrap 4,然後套上去,有人關心過 flex
的感受嗎?
沒有。
歐,對了,這一招可以強迫斷行,不要問我為什麼我會生氣!
flex-basis: 100%;
另外,當你使用 flex-direction: column
的時候,這個 flex-wrap
基本上是無效的。同樣可以參考我 比較近期 的幹話文章。
教練我想要對齊
通常來說,我們會很在意的地方應該是「垂直置中」對齊。這一點在 flex
裡面很容易實現,你只需要 align-items: center;
就收工了。
然後你會發現,在沒有特定高度的情況下會失效。
師父有交代,收工之前不能罵髒話。
關於對齊這件事情,Amos 寫了 23 種,我這邊就不野人獻曝了。