馬蹄疾 | 2019年,是時候認真學一波 Grid 佈局了

馬蹄疾發表於2019-03-26

馬蹄疾 | 2019年,是時候認真學一波 Grid 佈局了

上週,我寫的 Flex專題 被阮一峰的「每週分享第 48 期」收錄,然後 倉庫 就登上了子類的 GitHub Trending (流量太可怕了?)。

馬蹄疾 | 2019年,是時候認真學一波 Grid 佈局了

這一次是Flex專題的姊妹篇Grid專題。正巧昨天阮一峰也釋出了 Grid 佈局教程,大家可以切換著看吶 (我覺得我的寫得更好,不接受反駁?)。

本文是『horseshoe·Grid專題』系列文章之一,後續會有更多專題推出

GitHub地址(持續更新):horseshoe

部落格地址(文章排版真的很漂亮):matiji.cn

如果覺得對你有幫助,歡迎來 GitHub 點 Star 或者來我的部落格親口告訴我

Grid Layout叫柵格佈局模型,因為幾乎每一個成熟的CSS框架都會實現自己的柵格佈局系統,所以W3C乾脆弄了一套CSS原生的柵格佈局系統,補足這方面的短板。

有那麼一段時間,網頁佈局是表格的天下。用表格佈局雖然怪怪的,但是表格有它自己的優勢。流式佈局只能一個一個元素往頁面底部流動,它的表達能力是有限的;而表格把頁面切成若干豆腐塊,能從容調配每一塊豆腐,佈局表達能力秒殺。然而表格畢竟是表格,它有一些特性是專門為製作表格準備的,所以也就逐漸式微了。

柵格佈局系統,可以理解為更加通用、更加強大的表格佈局系統。它也是把頁面切成若干豆腐塊,元素可以自由宣告佔用哪個豆腐塊。W3C還為Grid Layout增加了好多專用的屬性、語法和計算函式,可以說,這一次是奔著一勞永逸來的。

二維佈局模型

我們之前講過Flexbox屬於一維佈局模型,詳情見:Flex專題

這個專題要講的Grid Layout則屬於二維佈局模型。

當我們的視角確立以後,所謂的一維就是隻有行,而所謂的二維就是有行也有列。很好理解,既然是柵格嘛,那必須得行列相交才能確定一個格子的大小。

概念

因為Grid Layout是二維佈局模型,它乾脆就固定了行與列的方向。格子嘛,任何橫著放的佈局方式都可以用豎著放的佈局方式實現,反之亦然。所以自定義主軸的方向意義不大,於是乎Grid Layout也就沒有主軸和交叉軸的概念。

Grid Layout唯一涉及到自定義方向的屬性是grid-auto-flow,它的意思是當格子沒有顯式宣告位置的時候,排列順序的方向如何確定,是按列排呢還是按行排。這個屬性後面會細講。

馬蹄疾 | 2019年,是時候認真學一波 Grid 佈局了

容器與專案

Grid Layout有柵格容器(grid container),它負責劃分領地,容器之內的元素才會臣服於柵格模型;Grid Layout也有柵格專案(grid item),它們是需要被柵格模型約束的物件。

柵格線

柵格線可以理解為柵格的邊框,水平和垂直的柵格線交叉形成了柵格單元。柵格線有什麼作用呢?有些柵格專案可能不止佔用一個柵格單元,宣告的時候就可以說我從第幾條柵格線開始,到第幾條柵格線結束,這塊區域是老子的

你可以為柵格線命名。

柵格單元

四條柵格線合圍成的最小區域就是柵格單元。它就是我們常說的格子。

需要特別區分柵格單元柵格專案

把柵格模型類比成養豬場的話,柵格單元就是豬圈,柵格專案就是豬。但是這裡的豬比較金貴,一個豬圈最多隻能養一頭豬。就是一個蘿蔔一個坑吧。

但有些豬比較肥,或者比較霸道,它可能佔用不止一個豬圈。

柵格單元是格子,柵格專案是元素,有時候一個元素只需要一個格子約束它,有時候一個元素需要多個格子約束它。

編外柵格單元

柵格單元的數量是需要顯式宣告的。如果柵格專案的數量超過了宣告的柵格單元的數量,Grid Layout就會自動建立若干柵格單元來包裹那些超出的柵格專案。

我們稱它為編外柵格單元。

編外柵格單元有自己的特性,可以通過grid-auto-columnsgrid-auto-rowsgrid-auto-flow自定義。

柵格系統

柵格系統就是柵格單元的總和。

柵格系統和柵格容器不是一個概念,正如柵格單元和柵格專案不是一個概念一樣。

柵格系統有可能溢位柵格容器,也可能偏居柵格容器的一隅,也可能充滿柵格容器。

柵格軌道

還是回到二維佈局模型,雖然我們說它有行也有列,但區分行與列的收益並不大,所以就統一叫它們柵格軌道。

兩條相鄰的柵格線與柵格容器合圍成的區域就是柵格軌道。

柵格區域

任意四條柵格線合圍成的區域都可以成為柵格區域。當一個元素需要多個格子約束它的時候,我們說這個元素需要一個柵格區域約束它。

柵格區域可以由一個柵格單元組成,也可以有若干個柵格單元組成,但它必須是一個長方體。

或者說,你用兩條水平線和兩條垂直線組成一個非長方體給我看看?

柵格區域最終是要被柵格專案使用的。你可以給柵格區域命名,柵格專案用名字宣告區域,或者柵格專案直接用四條柵格線確定一個區域。

display

從這裡開始,我們就要講具體的CSS屬性了。

這個屬性宣告的是柵格容器的型別。

.container {
    display: grid | inline-grid | subgrid;
}
複製程式碼

前兩個屬性值的區別在於容器自身應該表現為塊元素還是行內元素。第三個屬性值屬於CSS Grid Level 2規範,目前(2019年3月)還在草案階段,按下不表。

grid-template-[columns|rows]

這兩個屬性宣告的是柵格軌道的數量以及寬度。

當你宣告瞭四個寬度值,那在這個方向上就有四條軌道,它們的寬度是你宣告的值。

你也可以在宣告柵格軌道的同時宣告柵格線的名稱。順序就是它們的物理順序。

.container {
    grid-template-columns: <length> <length> | <line-name> <length> <line-name> <length> <line-name>;
    grid-template-rows: <length> <length> | <line-name> <length> <line-name> <length> <line-name>;
}
複製程式碼

任何適用於width的值都適用於這裡。

auto

如果某條柵格軌道的值是auto,預設情況下該柵格軌道會充滿柵格容器的富餘空間。

馬蹄疾 | 2019年,是時候認真學一波 Grid 佈局了

.container {
    display: grid;
    grid-template-columns: 100px auto 100px;
    grid-template-rows: repeat(2, 50px);
    grid-gap: 10px;
}
.item.b {
    width: 100px;
}
複製程式碼

但是如果宣告瞭justify-content(後面會講到)不為stretch,那auto會表現為以柵格專案的長度為準。

馬蹄疾 | 2019年,是時候認真學一波 Grid 佈局了

.container {
    display: grid;
    grid-template-columns: 100px auto 100px;
    grid-template-rows: repeat(2, 50px);
    grid-gap: 10px;
    justify-content: start;
}
.item.b {
    width: 50px;
}
複製程式碼

這不難理解。類比一下,普通的塊級元素會佔滿行內的富餘空間,絕對定位後的塊級元素會以自身或者子元素的寬度為寬度。auto在這裡的表現是一樣的。

fr

frfraction的縮寫,翻譯成中文是分數,多少分之一的分數。它是Grid Layout專用的長度單位。

它的計算公式是這樣的,首先減去非fr單位的長度,以富餘空間為總長度,以宣告的fr數量總和為分母,以自身宣告的fr數量為分子,求得自身所佔的長度。

馬蹄疾 | 2019年,是時候認真學一波 Grid 佈局了

.container {
    display: grid;
    grid-template-columns: 100px repeat(2, 1fr);
    grid-template-rows: repeat(2, 50px);
    grid-gap: 10px;
}
複製程式碼

為什麼W3C要增加一個這樣的單位呢?不是有%麼?

答案就在富餘空間上。fr也是一種百分比,但是它能保證總長度不會超過柵格容器的長度,因為它瓜分的是富餘空間的長度;而%瓜分的是柵格容器的長度,不管別人瓦上霜。

比如說像上面的例子,用%可得好好算算,用fr就簡單多了。

minmax()

minmax()Grid Layout專用的計算函式。

.container {
    display: grid;
    grid-template-columns: minmax(100px, 200px) 300px 300px;
}
複製程式碼

它有兩個引數,分別是最小值和最大值。當柵格單元需要壓縮時,最小值就是柵格專案被壓縮的最小極限,當柵格單元有剩餘空間時,最大值就是柵格專案擴張的最大極限。

它還有幾個值需要特別提一下。

  • max-content:它的值是柵格專案中的文字不換行的自然長度。
  • min-content:它的值是柵格專案中的文字全部換行的自然長度。
  • auto:它的值根據所處的場景介於min-content和max-content之間。

fit-content()

fit-content()也是Grid Layout專用的計算函式。

它接受一個長度單位的引數。

馬蹄疾 | 2019年,是時候認真學一波 Grid 佈局了

.container {
    display: grid;
    grid-template-columns: repeat(3, fit-content(200px));
    grid-template-rows: repeat(2, 50px);
    grid-gap: 10px;
}
複製程式碼

我們已經瞭解過min-contentmax-content

fit-content()計算公式形象的講,最小值是內容的min-content,最大值則取引數和max-content更小的那個。比如上面的例子,當內容小於200px時,以內容為長度,當內容大於200px時,以200px為長度。

repeat()

repeat()Grid Layout專用的重複函式。

它接受兩個引數,第一個引數是重複的次數,第二個引數是柵格軌道的寬度。

馬蹄疾 | 2019年,是時候認真學一波 Grid 佈局了

.container {
    display: grid;
    grid-template-columns: repeat(3, 100px);
    grid-template-rows: repeat(2, 50px);
    grid-gap: 10px;
}
複製程式碼

第二個引數不僅僅可以是寬度,它可以是一種模式。比如說[col-start] 100px [col-end] auto,它會重複這一整段若干遍,而中括號包圍的是給柵格線命名。

如此這般,第一、三、五條柵格線叫col-start,第二、四、六條柵格線叫col-end。總之用repeat函式命名柵格線會有很多重複的名字。

除此之外,第二個引數還可以是minmax函式、fit-content函式,或者min-contentmax-contentauto關鍵字。

馬蹄疾 | 2019年,是時候認真學一波 Grid 佈局了

.container {
    display: grid;
    grid-template-columns: repeat(3, [col-start] 100px [col-end] auto);
    grid-template-rows: repeat(2, 50px);
    grid-gap: 10px;
}
複製程式碼

第一個引數也有兩個關鍵字auto-fillauto-fit

馬蹄疾 | 2019年,是時候認真學一波 Grid 佈局了

.container {
    display: grid;
    grid-template-columns: repeat(auto-fill, 100px);
    grid-template-rows: repeat(2, 50px);
    grid-gap: 10px;
}
複製程式碼

馬蹄疾 | 2019年,是時候認真學一波 Grid 佈局了

.container {
    display: grid;
    grid-template-columns: repeat(auto-fit, 100px);
    grid-template-rows: repeat(2, 50px);
    grid-gap: 10px;
}
複製程式碼

稍微講解一下。

auto-fillauto-fit的共同點在於它們會保證柵格系統不溢位柵格容器。因為如果你寫死了重複多少個,柵格容器空間不夠的話只能溢位了。

而不同點在於,auto-fill會生成儘可能多的柵格軌道,即便這些軌道看起來沒什麼用;auto-fit則會生成儘可能少的柵格軌道,以便讓那些自適應的柵格單元儘可能佔用更多空間。

所以區別在於,auto-fill想讓柵格軌道盡可能多,auto-fit想讓柵格單元儘可能大。

這兩個屬性是Grid Layout自適應佈局的利器,連媒體查詢都省了。

.container {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
}
複製程式碼

這裡的意思是說,自適應佈局,每個柵格專案長度等分,但最小不低於300px。那最大怎麼確定呢?600px900px之間,一行只能放兩個專案,一旦超過900px,一行就會放三個專案。

grid-template-areas

這個屬性給柵格單元命名,同名的柵格單元自動成為一個柵格區域。

.container {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    grid-template-areas:
        'header header header'
        'sidebar main main'
        'footer footer footer';
}
複製程式碼

命名之後有什麼用呢?柵格專案有一個grid-area屬性,它來瓜分柵格區域。

.item {
    grid-area: header;
}
複製程式碼

這個意思是說,名字叫header的柵格區域都是我的,撒尿為證。

必須保證格式

grid-template-columnsgrid-template-rows宣告瞭多少個柵格單元,命名的時候需要名字與柵格單元一一對應起來。並且前面說過柵格區域必須是長方體,連續命名的時候也要注意這點。

我偏不一一對應呢?比如橫向上有三個柵格單元,但我只宣告兩個名字。

.container {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    grid-template-areas:
        'header header';
}
複製程式碼

或者我偏不湊一個長方體呢?比如第一行兩個main,第二行三個main

馬蹄疾 | 2019年,是時候認真學一波 Grid 佈局了

.container {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    grid-template-rows: repeat(2, 50px);
    grid-template-areas:
        'main main avatar'
        'main main main';
}
.item.a {
    grid-area: main;
}
複製程式碼

格式不對的話,結果都是一樣的。所有宣告瞭grid-area的專案都會在右下角的某個編外柵格單元內,重疊在一起,尚不清楚它的演算法或機制是怎樣的。

其實第二種情況,完全可以認為兩列四個main組成一個區域,另一個main組成另一個區域,是吧?但是你想想,現在有兩個叫main的區域,專案瓜分的時候很尷尬呀,有一塊飛地。格式還是不對。

所以呀,語法就是這麼嚴格,老老實實遵守。

預設名字

既然語法這麼嚴格,你要知道,取名字是一件腦殼疼的事情啊。我明明只需要給一小塊區域取名字,你非得讓我取滿。有沒有什麼省事的辦法呢?

當然有。不知道叫什麼的時候就用.代替。

.container {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    grid-template-areas:
        'main main sidebar'
        'main main .';
}
複製程式碼

不僅如此,只要沒有空格分開,n個.都只佔一個柵格單元。

grid-template-areas還有一個屬性值none。一開始我以為開啟方式是這樣的:

.container {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    grid-template-areas:
        'main main sidebar'
        'main main none';
}
複製程式碼

結果我其實宣告瞭一個叫做none的柵格區域。nonegrid-template-areas的預設值,實際開啟方式是這樣的:

.container {
    grid-template-areas: none;
}
複製程式碼

也就是說,別管它。

相關隱式宣告

每一個柵格區域都由四條柵格線包裹,這四條線同時會被隱式的賦予名稱。橫向上分別是xxx-startxxx-end,縱向上也是xxx-startxxx-end。反正柵格線名字不怕多,它只怕黑,因為它是黑怕歌手。

同時呢,反過來也是成立的。

.container {
    display: grid;
    grid-template-columns: [biu-start] 1fr [nothing] 1fr [biu-end] 1fr [nothing];
    grid-template-rows: [biu-start] 1fr [nothing] 1fr [biu-end];
}
複製程式碼

上面會隱式的宣告一個叫做biu的柵格區域。而且發現了沒有,柵格區域不可以重名,但是可以重疊。

grid-[column|row]-gap

這個屬性宣告的是柵格單元之間的空隙。

.container {
    grid-column-gap: <length>;
    grid-row-gap: <length>;
}
複製程式碼

這裡的值可以是任何定義width的值。

可以看到,如果將grid-column-gap設為80%,它的意思就是gap佔柵格容器的80%,所有柵格單元只能分剩下的20%

如果將grid-column-gap設為100%或超過100%呢?柵格單元的寬度不一定是0,因為在Flex專題中我們講過,marginborderpadding是很剛的,只要你定義了,flex或者grid完全無法壓縮它們。

特別需要注意的是,grid-[column|row]-gap無法使用fr單位的值。

配角戲份就不要太多了吧。

grid-gap

這是一個集合屬性,可以同時宣告grid-column-gapgrid-row-gap

.container {
    grid-gap: <grid-column-gap> <grid-row-gap>;
}
複製程式碼

justify-items

這個屬性宣告的是柵格單元相對於垂直柵格線的對齊方式。

.container {
    justify-items: stretch(default) | start | end | center;
}
複製程式碼

馬蹄疾 | 2019年,是時候認真學一波 Grid 佈局了

.container {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    grid-template-rows: repeat(2, 50px);
    grid-gap: 10px;
    justify-items: center;
}
複製程式碼

當柵格單元的總寬度大於柵格容器的寬度時,垂直柵格線會被撐開,也就不存在對齊了。

所以這個屬性只有在柵格單元的總寬度小於柵格容器的寬度時才生效。

Flexbox的類似屬性值有flex-startflex-end,W3C終於在grid上把字首去掉了。

align-items

這個屬性宣告的是柵格單元相對於水平柵格線的對齊方式。

.container {
    align-items: stretch(default) | start | end | center;
}
複製程式碼

place-items

這是一個集合屬性,可以同時宣告align-itemsjustify-items

如果省略第二個引數,則第二個引數會採用第一個值。

.container {
    place-items: <align-items> <justify-items>;
}
複製程式碼

justify-content

這個屬性宣告的是柵格系統相對於柵格容器的水平對齊方式。

.container {
    justify-content: start(default) | end | center | stretch | space-around | space-between | space-evenly;
}
複製程式碼

馬蹄疾 | 2019年,是時候認真學一波 Grid 佈局了

.container {
    display: grid;
    grid-template-columns: repeat(3, 100px);
    grid-template-rows: repeat(2, 50px);
    grid-gap: 10px;
    justify-content: center;
}
複製程式碼

如果柵格單元宣告的寬度都是非auto的值,那justify-content的預設值是start,也就是左對齊。這時候stretch是不起作用的。

如果有柵格單元的寬度值是auto,那它預設就是stretch,於是整個柵格系統也變成stretch。當然你可以將justify-content設定成別的值,這時候寬度值是auto的柵格單元就以子元素的寬度為寬度了。

所以我沒明白justify-content: stretch的作用是什麼。唯一的使用場景是樣式覆蓋的時候。

align-content

這個屬性宣告的是柵格系統相對於柵格容器的垂直對齊方式。

.container {
    align-content: start(default) | end | center | stretch | space-around | space-between | space-evenly;
}
複製程式碼

這裡關於stretch的處理是一樣的。

place-content

這是一個集合屬性,可以同時宣告align-contentjustify-content

如果省略第二個引數,則第二個引數會採用第一個值。

.container {
    place-content: <align-content> <justify-content>;
}
複製程式碼

grid-auto-[columns|rows]

這兩個屬性宣告的是編外柵格單元的高度和寬度。

.container {
    grid-auto-columns: <length> <length> <length>;
    grid-auto-rows: <length> <length> <length>;
}
複製程式碼

馬蹄疾 | 2019年,是時候認真學一波 Grid 佈局了

.container {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    grid-template-rows: repeat(2, 50px);
    grid-gap: 10px;
    grid-auto-rows: 100px;
    height: 300px;
}
複製程式碼

編外柵格單元的寬度預設值都是auto。也就是說,以寬度舉例,如果柵格容器的寬度大於柵格系統的寬度,那編外柵格單元會平分富餘空間的寬度,否則編外柵格單元就以內容的寬度為寬度了。

馬蹄疾 | 2019年,是時候認真學一波 Grid 佈局了

.container {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    grid-template-rows: repeat(2, 50px);
    grid-gap: 10px;
    height: 300px;
}
複製程式碼

馬蹄疾 | 2019年,是時候認真學一波 Grid 佈局了

.container {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    grid-template-rows: repeat(2, 50px);
    grid-gap: 10px;
    height: 110px;
}
複製程式碼

grid-auto-flow

這個屬性宣告的是如果柵格專案沒有明確指定在柵格容器中的位置時,柵格專案應該如何依次排列。

關於什麼叫明確指定位置,柵格專案自身有一些屬性,可以宣告它佔據的區域從哪條柵格線開始,到哪條柵格線結束,或者直接宣告佔據哪個柵格區域。這裡按下不表,後面會講到。

這個屬性有點像Flexbox的flex-direction屬性。

.container {
    grid-auto-flow: row(default) | column | dense | row dense | column dense;
}
複製程式碼

顧名思義,row就是按行排列,column就是按列排列。

馬蹄疾 | 2019年,是時候認真學一波 Grid 佈局了

.container {
    display: grid;
    grid-template-columns: repeat(3, 100px);
    grid-template-rows: repeat(2, 50px);
    grid-gap: 10px;
    grid-auto-flow: row;
}
複製程式碼

馬蹄疾 | 2019年,是時候認真學一波 Grid 佈局了

.container {
    display: grid;
    grid-template-columns: repeat(3, 100px);
    grid-template-rows: repeat(2, 50px);
    grid-gap: 10px;
    grid-auto-flow: column;
}
複製程式碼

重點要談談的是dense這個屬性值。dense翻譯成中文是稠密的意思,它的作用是當排在前面的柵格專案由於某些原因(主要是明確指定了位置,但是又沒有佔滿)空出了一些位置,後面的專案如果合身的話應不應該擠進去。

這麼幹的後果就是沒有明確指定位置的柵格專案可能不按順序排列。

馬蹄疾 | 2019年,是時候認真學一波 Grid 佈局了

.container {
    display: grid;
    grid-template-columns: repeat(3, 100px);
    grid-template-rows: repeat(2, 50px);
    grid-gap: 10px;
}
.item.c {
    grid-column-start: 2;
}
複製程式碼

馬蹄疾 | 2019年,是時候認真學一波 Grid 佈局了

.container {
    display: grid;
    grid-template-columns: repeat(3, 100px);
    grid-template-rows: repeat(2, 50px);
    grid-gap: 10px;
    grid-auto-flow: dense;
}
.item.c {
    grid-column-start: 2;
}
複製程式碼

grid

這是一個集合屬性,它可以宣告兩大類屬性中任一類的所有屬性值。

.container {
    grid: <grid-template-rows> / <grid-template-columns>;
    grid: <grid-auto-flow> [<grid-auto-rows> [/ <grid-auto-columns>]];
}
複製程式碼

以長度開頭的值宣告的就是第一類,以rowcolumndense開頭的值宣告的則是第二類。

以當前Grid Layout的普及程度來看,儘量不要這麼寫,你寫的費勁,別人看的費勁。

grid-[column|row]-[start|end]

從這裡開始,涉及到的屬性都是柵格專案自身的屬性。

這個屬性宣告的是指定柵格專案從哪裡開始到哪裡結束。

.item {
    grid-column-start: auto(default) | <number> | <name> | span <number> | span <name>;
    grid-column-end: auto(default) | <number> | <name> | span <number> | span <name>;
    grid-row-start: auto(default) | <number> | <name> | span <number> | span <name>;
    grid-row-end: auto(default) | <number> | <name> | span <number> | span <name>;
}
複製程式碼

start並不一定要比end靠前,靠後的話,開始到結束的方向就相反了。比如下面兩段程式碼指定的區域是一樣的。

.item {
    grid-column-start: 1;
    grid-column-end: 3;
}
複製程式碼
.item {
    grid-column-start: 3;
    grid-column-end: 1;
}
複製程式碼

我們來挨個講解各屬性值:

  • auto指的是隻佔用一個柵格單元。無論從哪開始,從哪結束,只要有一個auto值,它就只佔一個柵格單元。

  • number指的是柵格線的順序,從1開始。

  • name指的是柵格線的名稱。柵格線的名稱可以從兩個地方來,第一是通過grid-template-[columns|rows]顯示宣告,第二是定義grid-template-areas的同時會為合圍的柵格線自動生成xxx-startxxx-end的名稱。

  • span <number>指的是跨度為幾。這裡的數字不再是第幾條柵格線,而是跨越幾條几條柵格線。

  • span <name>指的是跨越到該名稱的柵格線為止。它和僅僅是name有什麼區別呢?如果startend靠後,僅僅是name的情況會像前面說的一樣,開始到結束的方向就相反;而span <name>的情況則會一直往後找,畢竟找不到嘛,所以就跨越到最後一條柵格線。其中的區別在於愣頭青的程度對不對?

馬蹄疾 | 2019年,是時候認真學一波 Grid 佈局了

.container {
    display: grid;
    grid-template-columns: repeat(3, 100px);
    grid-template-rows: repeat(2, 50px);
    grid-template-areas:
        'a b c'
        'd e f';
    grid-gap: 10px;
}
.item.c {
    grid-column-start: c-start;
    grid-column-end: a-start;
}
複製程式碼

馬蹄疾 | 2019年,是時候認真學一波 Grid 佈局了

.container {
    display: grid;
    grid-template-columns: repeat(3, 100px);
    grid-template-rows: repeat(2, 50px);
    grid-template-areas:
        'a b c'
        'd e f';
    grid-gap: 10px;
}
.item.c {
    grid-column-start: c-start;
    grid-column-end: span a-start;
}
複製程式碼

grid-[column|row]

這是兩個集合屬性,它們可以同時宣告在某個方向開始和結束的位置。

.item {
    grid-column: <start> / <end>;
    grid-row: <start> / <end>;
}
複製程式碼

grid-area

這個屬性宣告的是柵格專案佔據哪個柵格區域。

.item{
    grid-area: <name> | <row-start> / <column-start> / <row-end> / <column-end>;
}
複製程式碼

前面介紹過grid-template-areas屬性,它宣告的柵格區域就可以被柵格專案使用了。

當然你也可以使用柵格線的方式來合圍一個柵格區域,所以它也相當於grid-[column|row]-[start|end]的終極集合屬性。要特別注意宣告的順序。

馬蹄疾 | 2019年,是時候認真學一波 Grid 佈局了

.container {
    display: grid;
    grid-template-columns: repeat(3, 100px);
    grid-template-rows: repeat(2, 50px);
    grid-template-areas:
        'a b c'
        'd e f';
    grid-gap: 10px;
}
.item.c {
    grid-area: a; /* 或者 grid-area: 1 / 1 / 2 / 2; */
}
複製程式碼

justify-self

這個屬性宣告的是柵格專案的長度如果小於柵格單元的長度,柵格專案如何水平對齊。

通過它可以宣告該柵格專案自身的水平對齊方式,甚至可以覆蓋柵格容器justify-items的值。

.item {
    justify-self: stretch(default) | start | end | center;
}
複製程式碼

align-self

這個屬性宣告的是柵格專案的高度如果小於柵格單元的高度,柵格專案如何垂直對齊。

通過它可以宣告該柵格專案自身的垂直對齊方式,甚至可以覆蓋柵格容器align-items的值。

.item {
    align-self: stretch(default) | start | end | center;
}
複製程式碼

place-self

這是一個集合屬性,可以同時宣告align-selfjustify-self

如果省略第二個引數,則第二個引數會採用第一個值。

.item {
    place-self: <align-self> <justify-self>;
}
複製程式碼

其他

有一個小遊戲 Grid Garden 可以幫助你輕鬆的實踐Grid Layout的各項特性。

還有一個網站 GridByExample,號稱所有你需要知道的Grid Layout知識都在這裡。

本文是『horseshoe·Grid專題』系列文章之一,後續會有更多專題推出

GitHub地址(持續更新):horseshoe

部落格地址(文章排版真的很漂亮):matiji.cn

如果覺得對你有幫助,歡迎來 GitHub 點 Star 或者來我的部落格親口告訴我

相關文章