容器

我們先來看 Grid 的容器,他包含了 一張試算表 像是 Table 一樣的東西,為何會說他 像是 Table,我直接舉例給大家看就知道了,

.grid {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    grid-template-rows: repeat(4, 1fr);
}

.item1 {
    grid-column-start: 1;
    grid-column-end: 3;
    grid-row-start: 1;
    grid-row-end: 3;
}

HTML 長這樣,

<section class="grid">
    <div class="item item-1"></div>
    <div class="item"></div>
    <div class="item"></div>
    <div class="item"></div>
</section>

用 Table 來解釋,

/* 沒有 CSS */
<table>
    <tbody>
        <tr>
            <td colspan="2" rowspan="2"></td>
            <td></td>
            <td></td>
            <td></td>
        </tr>
        <tr>
            <td></td>
            <td></td>
        </tr>
        <tr>
            <td></td>
            <td></td>
            <td></td>
            <td></td>
        </tr>
        <tr>
            <td></td>
            <td></td>
            <td></td>
            <td>你是忘記了,還是害怕想起來</td>
        </tr>
    </tbody>
</table>

那就回去寫 Table 就好啦~我還可以支援 IE6/7/8/9/10/11 呢,好蚌蚌!

你走開,我暫時不想跟你說話。

好的,我們來看看 Grid 實際在瀏覽器裡面的狀況,

你在畫面中所看到的 虛線,就是 Grid 所排出來的 columnrow 的線,然後你就會得到 4 x 4 總共 16 個區塊。然後第一個區塊看起來很空曠,那是因為紅色的內容寬度固定為 100x100 的關係。如果我們把第一個區塊放大到 600x600 的時候,他就會變成這個樣子,

他就會超過原本設定的區域,而,這件事情是不是可以避免?

不行。

無論你是故意還是不小心,讓容器元件內的尺寸,比你的 Grid 規則還要大,他是沒有方式可以限制他的展示區域的。這一點跟 Table 的操作是完全不同的。整體來說,Grid 在畫面上是一種虛擬的排版結構,並沒有 硬性規定 元件內容一定要跟著結構的尺寸走。


新單位 fr

這個單位是在 Grid 推出之後,跟著推出的一種尺寸標記方式。他的全名叫做 ,引用一下 w3c 對此單位的說明,

A flexible length or <flex> is a dimension with the fr unit, which represents a fraction of the leftover space in the grid container. Tracks sized with fr units are called flexible tracks as they flex in response to leftover space similar to how flex items with a zero base size fill space in a flex container.

翻成中文就是,

彈性元件在單一方向上面的相對尺寸單位。

說到相對尺寸,你可能會馬上聯想到 % 這個單位設定。不過基本上,他跟百分比的設定又稍微不一樣。我們用剛剛的例子來說明這個差異,如果我的容器是固定寬度與高度,那麼,我的格線軌道(Grid Track)一樣使用 4 x 4,只是我們把單位換一下,換成 %。根據上一個段落的例子,如果我們需要平均分配成 4 x 4,那我們大概會知道就是 100% / 4 這樣的概念。

grid-template-columns: repeat(4, 25%);

好的,這樣看起來很合理。那麼,我們做一點比較騷包的操作,如果我想要的欄位格線軌道,是這樣的分配,

grid-template-columns: 2fr 1fr 1.5fr 1fr;

然後如果把他換成百分比,大概會是這樣,

grid-template-columns: 36.36% 18.18% 27.27% 18.18%;

然後畫出來就變成,

上面那個框框是使用百分比來定義,底下那個框框是使用 fr 單位定義。差異可能沒有很明顯,那麼,我們來做一個比較惡意的操作,

grid-template-columns: 20% 30% 40% 50%;

他會呈現這個結果,

來,我來解釋解釋上面發生了什麼事情,

  • 由於你的容器有指定寬度,上述例子是 800px,則元件參照容器尺寸來呈現他的寬度。
  • 容器的寬度換算出來,就分別是 160px, 240px, 320px400px
  • 總和超過 800px 也無所謂,只要你的容器沒有 overflow: hidden 就不會被遮斷。
  • 如果容器寬度是相對寬度,那麼這邊的容器尺寸就會繼續往外參考。
  • 如果容器寬度最終參考到無限大(或基本上等於螢幕寬度),則以螢幕最大寬度為主。

以上是 寬度 的狀況,如果把方向轉成行(rows)的話,他會有另一番風景,

  • 容器總高度(height)為 800px 的話(固定值),則運算規則跟寬度的方式相同。
  • 如果高度為相對數值,則往外參考,基本上也跟寬度一樣的計算方式。
  • 如果容器寬度最終參考到無限大(基本上網頁的設計就是沒有相對高度),則會用內容的 max-content 當作最大高度。

好的,我實在不太想解釋百分比的事情,如果你很熱愛用百分比的話,

你走開,我暫時不想跟你說話。

如果你可以理解這個畫面的話,你繼續用百分比沒關係。

好了,我覺得我在百分比花了太多廢話,總之,在確認狀況之前,請勿濫用百分比。接著,如果用 fr 把剛剛的百分比反過來翻譯的話,他的狀況大概會是,

我想要分配 2 份、3 份、4 份與 5 份。

先給畫面,然後我再來解釋 fr 怎麼處理 幾份 這件事情。

在格線系統遇到無限大尺寸時(例如無高度設定容器),他會取出該格線軌道上(rowscolumns)的元件內容填充的尺寸,來當作基本尺寸,而這個基本尺寸 會取最大內容尺寸 來當基準(不要問我為何不是最小)。然後,就會使用這個最大內容尺寸當作 1fr 來做計算。

所以他的計算方式就是,

Find the Size of an fr

另外,如果這個 fr 的數字介於 01 之間的話,他會取決於上述提到的 leftover-space,如果元件沒有剩餘任何空間,則會被強迫設定成最小容器元件的尺寸,在這個時候就很類似 min-content 的作法。但是!

但是!

強迫設定成 min-content 這個作法,是在無限大尺寸的狀況下會發生。

所以,你不要問我為何這個不是用 min-content 我會生氣!

grid-template-columns: 0.3fr 1fr 1fr 1fr;

任何橫向內容,你的裝置尺寸就是寬度天然屏障,不會有無限大尺寸的情況發生。

懂?


所以說那個手機版

如果你把每個段落設定成 100vh,然後做一下非同步捲軸,那麼你裡面的資料用 Grid 排也不是不行。畢竟所謂的「行動裝置」不僅僅只有手機,現在的電視也是行動裝置的一種,只是通常他不會動,然後通常會出現在客廳這樣而已。