間隔、間隔、間隔
先不囉唆,上圖。
中間看起來比較密集的部分,就是所謂的 間隔,在樣式表當中就是這樣設定,
.grid {
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-template-rows: repeat(4, 1fr);
grid-gap: 1rem;
}
這邊能夠接受的數值除了 fr
不能用以外,其他數字你要怎麼寫都可以。你也可以把間隔設定的比元件尺寸還要大,但是應該不會有人做這種事情吧。那麼,這個間隔有什麼毛病呢?請你回去看看剛剛那張圖。
看到那個精美的內容衝到間隔裡面了嗎?
是的,這跟昨天在說明 Grid 規則跟尺寸的部分相同。他無法硬性規定你的元件不能超過格線軌道的尺寸限制,所以,你所設計的間隔如果遇到這種狀況,並不能真實反應兩個元件之間是否一定存在有這樣的間距。在這個時候,你是不是開始懷念 float: left;
然後 margin: 0 15px
這種設計了。
所以,從 grid-template
到 grid-gap
整組的容器大結構來看,基本上就是設計一個有格線軌道的容器,然後,然後就沒有然後了。不然你覺得 Grid Layout Module 還能做什麼事情呢?
好啦,我後面可以告訴你一些八奇的用法。
合併、重複與空區塊
在格線系統當中,有一個很特別的屬性,可以針對格線區塊來命名,
.grid {
display: grid;
grid-template-areas:
"head head head"
"lefthand body lover"
". foot ."
}
我們沒有特別指定 rows
或 columns
,直接使用 grid-template-areas
來指定需要的區塊,並且賦予他們名字,我們現在就來看看上面那樣的設定代表哪些事情。
- "head head head" 代表我有一個
1 row x 3 columns
的區塊,他們的 名字都一樣,表示他會變成 合併儲存格。 - "lefthand body righthand" 格線區塊同上,但是他們不會合併,是獨立的區塊。
- ". foot ." 格線區塊同上,但由於使用了
.
,所以這個區塊不會被使用(變成空白區塊)。
所以,上面的設定就會變成一個 3 x 3
的格線容器。這個時候,倘若你設定了 rows
或 columns
的話,如果設定的容器比較大,就會從 3 x 3
長大,如果比 areas
設定的小,那麼最小就會使用 3 x 3
的格線容器。
接著,你要把容器元件放到 指定名稱的區塊,所以就會變成這樣的設定,
.grid .head {
grid-area: head;
}
.grid .foot {
grid-area: foot;
}
.grid .lefthand {
/* 左手只是輔助 */
grid-area: lefthand;
}
.grid .lover {
grid-area: lover;
}
.grid .body {
grid-area: body;
}
好的,如果說 指定位置 的動作在樣式表當中就做好了,那麼我 HTML 要做什麼?
就像你問男(女)朋友晚餐要吃什麼?
隨便。
所以 HTML 可以這樣寫也沒關係,
<section class="grid">
<div class="item foot"></div>
<div class="item lover"></div>
<div class="item body"></div>
<div class="item lefthand"></div>
<div class="item head"></div>
</section>
千萬不要,好嗎。
雖然格線系統的目的是讓你排版,但是不代表你可以惡搞 DOM 結構。另外,如果你用了一個沒有被命名的區塊,他還是會畫出來給你。你覺得他會放在哪裡?
<section class="grid">
<div class="item foot"></div>
<div class="item lover"></div>
<div class="item body"></div>
<div class="item lefthand"></div>
<div class="item head"></div>
<div class="item r20"></div>
</section>
.grid .r20 {
grid-area: r20;
}
我先把結果放上來,然後你自己想想他放在什麼地方。
好的,這個放置位置就跟格線系統的填滿規則有關。當你的元件放在一個 不存在 的區塊,他會有兩種反應,
- 如果是命名區塊不存在或沒指定名稱,會先去放置到第一個空區塊,並依序把空區塊放滿。
- 如果空區塊都被放滿了,則依照格線稀疏排列方式繼續往下排列。
- 如果是元件指定位置,則會把格線軌道長大到那個尺寸,然後把元件放在那個位置上。
來,我們看看指定位置超出容器的狀況,
.grid .r20 {
grid-column: 5 / 6;
grid-row: 2 / 3;
}
最終你會得到這樣的結果,
你會得到一個 變大 的格線容器。好的,這樣可以理解空區塊,命名區塊跟超出容器設定的差異了吧。另外,在格線系統中,剛剛提到的間隔,每個間隔其實也可以命名,舉例來說,
.grid {
grid-template-columns: [first] 1fr [two] 1fr [lala] 1fr [lol] 1fr [column-end];
grid-template-rows: [hello] 1fr [r20] 1fr [world] 1fr [last] 1fr [row-end];
}
命名方式有很多種變形,例如可以多組名字,
.grid {
grid-template-columns: [first] 1fr [first-end two] 1fr [two-end lala] 1fr [lol] 1fr [column-end];
grid-template-rows: [hello] 1fr [r20] 1fr [world] 1fr [last] 1fr [row-end];
}
當中的 [first-end two]
就代表這個間隔有兩個名字。然後,
grid-template-columns
跟grid-template-rows
會覆蓋grid-template-areas
的尺寸。
舉例來說,把剛剛上面的 grid-template-areas
合併起來看,
.grid {
display: grid;
grid-template-columns: [first] 1fr [two] 1fr [lala] 1fr [lol] 1fr [column-end];
grid-template-rows: [hello] 1fr [r20] 1fr [world] 1fr [last] 1fr [row-end];
grid-template-areas:
"head head head"
"lefthand body lover"
". foot ."
}
他就會變成 4 x 4
然後中間有包含一個有命名的 grid-template-areas
。然後,關於 grid-template-columns
跟 grid-template-rows
這邊有三種特殊設定可以使用,
span <命名間隔>
跨過<命名間隔>
的格線,直到碰觸到下一個格線為止。span <數字 N>
跨過 指定數字 N 個間隔。<命名間隔> <負數 N>
指到<命名間隔>
後,往回算 N 個間隔。
請注意 span
的使用,如果指定到的 <命名間隔>
不存在,就會直接接到容器的最後面。如果 <數字 N>
加上開始格線,超過容器的尺寸,容器會直接被擴大。舉例來說,
.grid .r20 {
grid-column-start: 1;
grid-column-end: span 30;
grid-row-start: 2;
grid-row-end: span 29;
}
這樣你就會獲得 30 x 30
的容器。是的,容器本身並不會硬性規定可容納的區塊,倘若內部區塊設定有不符合的地方,那麼他就會自己擴充到剛好可以放得下的那個尺寸。這一點在規劃、設計格線系統元件時,需要特別留意。
或者你會說,那我就不要設定容器的尺寸就好啦,反正元件要長由他長,要跳位置就跳位置啊。
你一定是甲方派來臥底的對不對!
所以說那個手機版
所以當我們的行動裝置需要複雜規劃時,利用 Grid 來做一些相對複雜的卡片內容排版是合理的。只是說,通常也不會複雜到 Flex 無法應付的狀況。如果有的話,先看一下甲方的誠意再說。