當我們定義好一個 flex 的容器時,昨天有說過了,預設會使用 row 這個設定來定義容器的流向。所以,在容器定義好的當下,我們把基本的容器設定展開來看,另外,我們賦予他 wrap 的設定,避免當中的元件被切掉,

.flexbox {
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
    /* 以上等同於 */
    /* flex-flow: row wrap; */
    width: 100%;
}

關於容器內容的流向、邊界、對齊等等,我們可以簡單的說明如下,

這是基本的 flex 容器流向,其中相對複雜一點點的,大抵上跟對齊還有 wrap-reverse 有關,關於 wrap-reverse 的部分,看圖就好我不太想解釋。

然後對齊的部分,有兩個系列的參數可以使用,

  • justify-content
  • justify-self
  • justify-items
  • align-content
  • align-self
  • align-items

這些參數應用的地方不同,

參數 維度 對齊 應用範圍
justify-content 主軸方向,內部元件流 區塊外部 區塊容器、Flex 容器與 Grid 容器
align-content 不分軸,區塊 區塊外部 區塊容器、Flex 容器與 Grid 容器
justify-self 內部元件流 自身元件相對於容器 區塊元件、絕對定位區塊元件與 Grid 元件
align-self 不分軸,區塊 自身元件相對於容器 絕對定位區塊元件、Flex 元件與 Grid 元件
justify-items 內部元件流 容器內所有元件 區塊容器與 Grid 容器
align-items 內部元件流 容器內所有元件 Flex 容器與 Grid 容器

請留意一下,我們目前是使用 flex 的容器,所以像是 justify-itemsjustify-self 在這邊就會無法使用。這些參數有這些數值可以使用,

  • center, start, end, self-start, self-end, flex-start, flex-end, left, right
  • baseline, first baseline, last baseline
  • stretch, space-between, space-around, space-evenly

然後,在 flex 系統中,關於 margin-* 有一個字會變一些魔術,

.item {
    margin-left: auto;
}

這個 auto 會幫你自動補白,

他用在上下左右四個方向都可以,所以如果你設定 margin: auto 的話,在固定高度的 Flex 容器當中,他就會垂直置中對齊。

是不是好蚌蚌!

但是,這個 margin 的設定,會覆蓋 justify-contentalign-items 的相關設定,也就是說,若你原本是設定 justify-content: flex-start;,然後你的元件又加上 margin-left: auto; 的話,你的 flex-start 設定就會被這個元件無視。


巢狀結構

這樣看起來 Flex 容器好棒棒,我如果要對齊的話就一直用 Flex 容器就好了~

<main>
    <section class="flex-1">
        <div class="flex-card">
            <div class="card header flex-header">
                <p>No. 1</p>
                <button type="button" class="close">x</button>
            </div>
            <div class="card body flex-body">
                <img src="/static/image.png" alt="Card Image">
                <h2 class="title flex-title">
                    <span>Hello World</span>
                    <button type="button">Like</button>
                </h2>
                <p class="author">Hina</p>
                <p class="description">天地之間講幹話</p>
            </div>
            <div class="card footer flex-footer">
                <button type="button">Details</button>
            </div>
        </div>
    </section>
</main>

千萬不要這樣做。

如果對方開價 20 萬的話,我可以。

我們回提到先前提到的一句話,

Grid for layout, flexbox for component.

再回到剛剛的 flex-card 那件事情,我們把我們的視角縮小,這邊的 flex-card 其實就比較適合使用 Grid 來設計「結構」,然後結構的內容交給 Flex 容器來製作。雖然這樣講起來,好像把 Grid 應用在這邊有點小題大作。但這樣的使用情境其實是符合的,還記得 Flex 容器的「單維度」的設計嗎?

如果要同時做到複雜元件的對齊,你就必須重複封裝 Flex 元件,在後續維護上並不是一件好事。如果你覺得 Grid 很難很不好理解,這邊有一個玩具可以先玩玩看。

LayoutIt!

或者是你繼續看我講幹話講到 Grid 也是不錯的選擇。


所以說那個手機版

請注意「尺寸」造成的問題。通常在設計行動裝置時,我們會將容器設計成 width: 100% 來包含畫面中的元件。那麼,當你設定你的 Logo 圖片是 200px 的時候,你想要元件是響應式的改變間距、排版,但是,同時也會改到「尺寸」,當你的 flex-shrink1 以上的時候。

所以你會發現多數的 Flex 容器內元件,都設計為 flex: 0 0,例如 Bootstrap 4 會像是這樣,

.col-6 {
    flex: 0 0 50%;
    max-width: 50%;
}

用意就是,不會自己長大,也不會被壓縮,就是要設定成相對尺寸 50% 的狀態。所以在行動裝置上,這樣的格線系統就是 幫你畫出固定尺寸的格子,剩下的事情就是你自己的事情了。