寫給自己看的display: grid佈局教程
byzhangxinxu from ofollow,noindex" target="_blank">https://www.zhangxinxu.com/wordpress/?p=8144
本文可全文轉載,個人網站無需授權,只要保留原作者、出處以及文中連結即可,任何網站均可摘要聚合,商用請聯絡授權。
一、前言&索引
給 <div>
這類塊狀元素元素設定 display:grid
或者給 <span>
這類內聯元素設定 display:inline-grid
,Grid佈局即建立!例如:
div { display: grid; }
此時該div就是“grid容器”,其子元素稱為“grid子項”。在Grid佈局中,所有相關CSS屬性正好分為兩撥,一撥作用在grid容器上,還有一撥作用在grid子項上。具體參見下表,點選可快速索引。
作用在grid容器上 | 作用在grid子項上 |
---|
Grid佈局相關CSS屬性雖然很多,但是實際上都不難理解,難的是這些屬性不太容易記住,需要多多實戰手寫才能信手拈來。
Grid佈局是一個二維的佈局方法,縱橫兩個方向總是同時存在。其中的很多佈局概念跟中國農田的佈局是完全匹配的。
因此,在我看來,Grid佈局就像是“分田種地”。故事是這樣的,張老闆是個程式員,省吃儉用攢了點小錢,然後老家因為城鎮化建設,農村都沒什麼人,土地都荒廢在那裡,於是就承包了一塊地,打算養養魚,種種果樹。承包的地方很挺大,如何劃分土地就成了問題,於是張老闆打算藉助Grid佈局來劃分。
二、作用在grid容器上的CSS屬性
1. grid-template-columns和grid-template-rows
這兩個CSS屬性用來對田地進行基本的劃分,columns是列的意思,表示豎直方向的劃分;rows是行的意思,表示水平方向的劃分。現實世界中,農田的佈局構造一般下面兩種:
- 田地A-田地B,下面是土地C-土地D,就是“田”這個字的構造,只不過4塊地之間分隔就是個不能走路的小溝溝,寬度可以忽略不計。
- 田地A-田壟-田地B,下面是土地C-田壟-土地D,也是“田”這個字的構造,只不過4塊地之間分隔是個可以走路的田壟,有的地方也叫土埂。
這裡的劃分語法就和上面的農田劃分一致,如下:
.container { grid-template-columns: <track-size> ... | <line-name> <track-size> ...; grid-template-rows: <track-size> ... | <line-name> <track-size> ...; }
用中文表示就是:
.container { grid-template-columns: <田地> ... 或 <田壟> <田地> ...; grid-template-rows: <田地> ... 或 <田壟> <田地> ...; }
也就是:
- <track-size> :劃分田地的尺寸。可以是長度值,百分比值,以及(網格剩餘空間比例單位)。
- <line-name> :中間用來走路的田壟的名字,可以任意命名。
看一個簡單例子:
.container { grid-template-columns: 80px auto 100px; grid-template-rows: 25% 100px auto 60px; }
grid-template-columns
後面3個值,表示分為了3列,從左往右每列的尺寸分別是 80px
,auto(自動)和 100px
;
grid-template-rows
屬性值含4個值,表示分為了4行,從上往下每行的高度分別是 25%
, 100px
,auto(自動)和 60px
。
實時效果如下所示:
寬80px
高25%
寬auto
高25%
寬100px
高25%
寬80px
高100px
寬auto
高100px
寬100px
高100px
寬80px
高auto
寬auto
高auto
寬100px
高auto
寬80px
高60px
寬auto
高60px
寬100px
高60px
我們還可以給“田壟”,也就是網格分隔線進行命名,語法是使用 []
包裹我們自定義的命名,可以是中文,例如:
.container { grid-template-columns: [第一根縱線] 80px [縱線2] auto [縱線3] 100px [最後的結束線]; grid-template-rows: [第一行開始] 25% [第一行結束] 100px [行3] auto [行4] 60px [行末]; }
實時效果如下,選中對應網格線的名稱可以高亮其位置:
寬80px
高25%
寬auto
高25%
寬100px
高25%
寬80px
高100px
寬auto
高100px
寬100px
高100px
寬80px
高auto
寬auto
高auto
寬100px
高auto
寬80px
高60px
寬auto
高60px
寬100px
高60px
為何要給網格線命名呢?
Grid佈局的好比街道劃分,田地劃分,這中間分隔的線通常就是道路或者田壟,如果我們不給這些道路起個名字,回頭想要描述某片區域的時候就不好描述。比方說:
南京東路東起外灘即中山東一路,西至西藏中路。
因為我們給道路命了名稱,因此,我們在描述某個區域的時候,就好描述,別人也好辨認。但如果沒有命名,而是下面這樣描述:
南京東路東起靠近黃浦江第1條路,靠近黃浦江第8條路。
得,這個區域描述就有問題,萬一哪天封路,或者新建了條路,豈不就混亂了?
也就是說,給Grid佈局中的分隔線命名,為的就是可以更好地對區域進行描述。如果我們沒有描述某片區域的的需求,自然也不需要命名了。
雙命名
由於網格中中間區域的網格線是兩邊格子公用的,就像道路有兩邊,因此,我們起名字的時候可以起兩個名稱(使用空格分隔),分別表示兩側。例如:
.container { grid-template-columns: [第一根縱線] 80px [第1根縱線結束 第2根縱線開始] 100px [最後的結束線]; }
repeat語法
有時候,我們網格的劃分是很規律的,例如,基於 40px
建立柵格,要是我們佈局寬度 960px
,豈不是要寫24次 40px
,實在套囉嗦了,此時,就可以使用 repeat()
語法,如下示意:
.container { grid-template-columns: repeat(24, 40px [col-start]); }
等同於:
.container { grid-template-columns: 40px [col-start], 40px [col-start], /* ...省略20個...*/, 40px [col-start], 40px [col-start]; }
fr單位是什麼?
fr
是單詞fraction的縮寫,表示分數。
-
先從簡單例子看起:
.container { grid-template-columns: 1fr 1fr 1fr; }
1:1:1,網格寬度三等分,實時效果如下:
寬1fr
佔據1/3
寬1fr
佔據1/3
寬1fr
佔據1/3
-
如果有固定尺寸值,則劃分剩餘空間大小,例如:
.container { grid-template-columns: 200px 1fr 1fr 1fr; }
4列,後面3列寬度是grid容器寬度減去200畫素後的1/3大小,實時效果如下:
寬200px
寬1fr
寬1fr
寬1fr
-
如果和auto混用會如何呢?
.container { grid-template-columns: auto 1fr 1fr 1fr; }
寬auto
寬1fr
寬1fr
寬1fr
從上面效果可以看出,當有設定
fr
尺寸的時候,auto
的尺寸表現為“包裹”,為內容寬度。如果沒有設定fr
尺寸的網格,則表現為拉伸。 -
如果
fr
數值之和小於1又當如何?.container { grid-template-columns: auto 0.25fr .25fr .25fr; }
寬auto
寬0.25fr
寬0.25fr
寬0.25fr
這裡計算就相對複雜些,首先,由於第一個網格尺寸設定為 auto
,因此 fr
計算需要的剩餘空間尺寸是grid容器的寬度減去“寬auto”這幾個字元的寬度。所以,後面3個 0.25fr
元素的寬度是: (容器寬度 - “寬auto”字元寬度) * 0.25
。然後剩餘尺寸就是第一個網格寬度。
2. grid-template-areas
area是區域的意思, grid-template-areas
就是給我們的網格劃分區域的,就好像張老闆承包的土地劃分不同區域養殖不同的農作物或者水產品。
語法如下:
.container { grid-template-areas: "<grid-area-name> | . | none | ..." "..."; }
其中:
- grid-area-name
- 對應網格區域的名稱。
- .
- 表示空的網格單元格。
- none
- 沒有定義網格區域。
我們還是通過案例瞭解這個CSS屬性。張老闆承包了一塊地,然後劃分成了3*4共12個小格子,然後張老闆希望最上面3個格子種葡萄,最下面3個格子種西瓜,中間6個格子,左邊2個養龍蝦,右邊4個養魚。如下圖示意:
則對應CSS程式碼如下:
.container { grid-template-columns: 1fr 1fr 1fr; grid-template-rows: 1fr 1fr 1fr 1fr; grid-template-areas: "葡萄 葡萄 葡萄" "龍蝦 養魚 養魚" "龍蝦 養魚 養魚" "西瓜 西瓜 西瓜"; }
12個格子,四片區域,因此,我們grid子項只需要4個元素即可,HTML示意如下:
<div class="container"> <div class="putao"></div> <div class="longxia"></div> <div class="yangyu"></div> <div class="xigua"></div> </div>
此時grid子項只要使用 grid-area
屬性指定其隸屬於那個區域就可以了(支援中文區域名稱):
.putao { grid-area: 葡萄; } .longxia { grid-area: 龍蝦; } .yangyu { grid-area: 養魚; } .xigua { grid-area: 西瓜; }
實時Grid佈局效果如下:
葡萄種植區
龍蝦養殖區
魚類養殖區
西瓜種植區
注意:如果我們給網格區域命了名,但是沒有給網格線命名,則會自動根據網格區域名稱生成網格線名稱,規則是區域名稱後面加 -start
和 -end
。例如,某網格區域名稱是“葡萄”,則左側column線名稱就是“葡萄-start”,左側column線名稱就是“葡萄-end”。
以及,我們的網格區域一定要形成規整的矩形區域,什麼L形,凹的或凸的形狀都是不支援的,會認為是無效的屬性值。
//zxx: 實際開發的時候,葡萄種植區就是頭部區域,龍蝦就是側邊欄區域,魚類養殖區就是主區域,西瓜種植區就是底部區域。
3. grid-template
grid-template
是 grid-template-rows
, grid-template-columns
和屬性的縮寫。
語法如下:
.container { grid-template: none; } .container { grid-template: <grid-template-rows> / <grid-template-columns>; }
其中 none
表示將3個CSS屬性都設定為初始值。
舉個例子,前面張老闆養殖區劃分,用 grid-template
縮寫表示就是:
.container { grid-template: "葡萄 葡萄 葡萄" 1fr "龍蝦 養魚 養魚" 1fr "龍蝦 養魚 養魚" 1fr "西瓜 西瓜 西瓜" 1fr /1fr 1fr 1fr; }
實時效果如下:
葡萄種植區
龍蝦養殖區
魚類養殖區
西瓜種植區
由於 grid-template
不會重置一些隱式的grid屬性(如,和),因此,大多數時候,還是推薦使用代替 grid-template
。
4. grid-column-gap和grid-row-gap
grid-column-gap
和 grid-row-gap
屬性用來定義網格中網格間隙的尺寸。你可以理解成田地之間走路的田壟寬度。
語法如下:
.container { grid-column-gap: <line-size>; grid-row-gap: <line-size>; }
其中:
- <line-size>
- 網格間的間隙尺寸。
例項說話,給定一個簡單的2×2網格,設定水平網格間隙 10px
,垂直方向 15px
,如下:
.container { grid-template-columns: 2fr 1fr; grid-template-rows: 1fr 2fr; grid-column-gap: 10px; grid-row-gap: 15px; }
瀏覽器實時佈局渲染如下:
5. grid-gap
CSS grid-gap
屬性是 grid-column-gap
和 grid-row-gap
屬性的縮寫。語法如下:
.container { grid-gap: <grid-row-gap> <grid-column-gap>; }
先橫row後豎column,這個比較好記憶,古語有云:“橫豎都是死”,先橫後豎,網格的間隙就像是漢字“田”中間的那個“十”,按照漢字書寫,先橫後豎,就記住了。
例如,上面的2×2網格間隙案例也可以寫作:
.container { grid-template-columns: 2fr 1fr; grid-template-rows: 1fr 2fr; grid-gap: 15px 10px; }
效果一樣的,這裡就不佔據篇幅重複示意了。
6. justify-items
justify-items
指定了網格元素的水平呈現方式,是水平拉伸顯示,還是左中右對齊,語法如下:
.container { justify-items: stretch | start | end | center; }
其中:
- stretch
- 預設值,拉伸。表現為水平填充。
- start
- 表現為網格水平尺寸收縮為內容大小,同時沿著網格線左側對齊顯示(假設文件流方向沒有變)。
- end
- 表現為網格水平尺寸收縮為內容大小,同時沿著網格線右側對齊顯示(假設文件流方向沒有變)。
- center
- 表現為網格水平尺寸收縮為內容大小,同時在當前網格區域內部水平居中對齊顯示(假設文件流方向沒有變)。
各個屬性值實時效果如下(點選單選框體驗不同屬性值佈局效果):




7. align-items
align-items
指定了網格元素的垂直呈現方式,是垂直拉伸顯示,還是上中下對齊,語法如下:
.container { align-items: stretch | start | end | center; }
其中(假設文件流方向為網頁預設):
- stretch
- 預設值,拉伸。表現為垂直填充。
- start
- 表現為網格垂直尺寸收縮為內容大小,同時沿著上網格線對齊顯示。
- end
- 表現為網格垂直尺寸收縮為內容大小,同時沿著下網格線對齊顯示。
- center
- 表現為網格垂直尺寸收縮為內容大小,同時在當前網格區域內部垂直居中對齊顯示。
各個屬性值實時效果如下(點選單選框體驗不同屬性值佈局效果):




8. place-items
place-items
可以讓 align-items
和 justify-items
屬性寫在單個宣告中。語法如下:
.container { place-items: <align-items> / <justify-items>; }
這裡順序是 align-items
在前, justify-items
在後。首字母a,j,a,j,a,j,口中不斷重複,有沒有發現跟angelababy發音很像,沒錯,記住angelababy我們也就記住這裡的順序了。又或者有句古話,叫做“合縱連橫”,這種網格對齊,就有“合縱連橫”的意味在裡面,縱在前,橫在後,也可以方便我們記憶。
據說Edge15之前版本不支援 place-items
屬性(自己未實測),因此,如果有相容性顧慮,建議還是分開書寫。
9. justify-content
justify-content
指定了網格元素的水平分佈方式。此屬性僅在網格總寬度小於grid容器寬度時候有效果。例如,我們網格設定的都是固定的寬度值,結果還有剩餘空間。例如:
.container { display: grid; width: 300px; grid-template: 100px 100px/100px 100px; }
此時,水平和垂直方向都有100px的剩餘, justify-content
屬性此時就有用武之地了。
語法如下:
justify-content: stretch | start | end | center | space-between | space-around | space-evenly;
其中:
- stretch
- 預設值。拉伸,寬度填滿grid容器,拉伸效果需要網格目標尺寸設為auto時候才有效,如果定死了寬度,則無法拉伸。
- start
- 預設值。邏輯CSS屬性值,與文件流方向相關。預設表現為左對齊。
- end
- 邏輯CSS屬性值,與文件流方向相關。預設表現為右對齊。
- center
- 表現為居中對齊。
- space-between
- space-around
- space-evenly
眼見為實,點選下面對應單複選框,可以看到實時的佈局效果:




上面案例和下面案例中的grid佈局相關CSS都是:
.container { grid-template: auto auto/auto auto; }
10. align-content
align-content
可以看成和 justify-content
是相似且對立的屬性, justify-content
指明水平方向grid子項的分佈方式,而 align-content
則是指明垂直方向每一行grid元素的分佈方式。如果所有grid子項只有一行,則 align-content
屬性是沒有任何效果的。
語法如下:
align-content: stretch | start | end | center | space-between | space-around | space-evenly;
其中:
- stretch
- 預設值。每一行flex子元素都等比例拉伸。例如,如果共兩行flex子元素,則每一行拉伸高度是50%。
- start
- 邏輯CSS屬性值,與文件流方向相關。預設表現為頂部堆砌。
- end
- 邏輯CSS屬性值,與文件流方向相關。預設表現為底部堆放。
- center
- 表現為整體垂直居中對齊。
- space-between
- 表現為上下兩行兩端對齊。剩下每一行元素等分剩餘空間。
- space-around
- 每一行元素上下都享有獨立不重疊的空白空間。
- space-evenly
- 每一行元素都完全上下等分。
眼見為實,我們給flex容器設定高度500畫素,然後點選下面對應單選框,可以看到實時的佈局效果:




11. place-content
place-content
可以讓 align-content
和 justify-content
屬性寫在一個CSS宣告中,也就是俗稱的縮寫。語法如下:
.container { place-items: <align-content> / <justify-content>; }
這裡順序是 align-content
在前, justify-content
在後。首字母a,j,a,j,讀個幾遍,是不是和angelababy發音一致,記住angelababy就記住這裡的順序了。又或者有句古話,叫做“合縱連橫”,這種網格分佈,就有“合縱連橫”的意味在裡面,縱在前,橫在後,也可以方便我們記憶。
據說Edge15及其之前版本尚不支援 place-content
屬性(自己未實測),因此,如果有相容性顧慮,建議還是分開書寫。
12. grid-auto-columns和grid-auto-rows
指定任何自動生成的網格軌道(也稱為隱式網格軌道)的大小。 當網格專案多於網格中的單元格或網格專案放置在顯式網格之外時,將建立隱式軌道。
用張老闆承包土地的案例解釋就是:
- 土地劃分,計劃分成16塊區域搞農業,材料都買好了,結果發現承包的土地只能放下12塊區域,多的4塊怎麼辦呢?就在承包土地外面種點東西,不要浪費。
- 土地劃分,計劃上面種葡萄,底部種西瓜。但是,種植的時候搞錯了,西瓜種到了承包區域之外。
上面這兩種情況都是因為各種原因在自己土地之外也種了東西。如果張老闆想要對不在自己土地上的種植區域也進行尺寸規劃,該怎麼辦?此時就需要用到 grid-auto-columns
和 grid-auto-rows
屬性,就是應付這種場景的。
//zxx: 在Grid佈局中,這些非正常網格稱為“隱式網格”,在規定容器內顯示的稱之為“顯式網格”。
語法如下:
.container { grid-auto-columns: <track-size> ...; grid-auto-rows: <track-size> ...; }
其中:
- <track-size>
- 劃分田地的尺寸。可以是長度值,百分比值,以及(網格剩餘空間比例單位)。
我們通過一個例項來感受下 grid-auto-columns
和 grid-auto-rows
屬性的樣式表現。CSS如下:
.container { display: grid; width: 150px; grid-template-columns: 60px 60px; grid-template-rows: 30px 90px; grid-auto-columns: 60px; } .item-a { grid-column: 1 / 2; grid-row: 2 / 3; } .item-b { /* 容器水平只有2個格子,但這裡設定的是第3個,隱式網格建立 */ grid-column: 3 / 4; grid-row: 2 / 3; background-color: rgba(255,255,0, .5); }
實時效果如下, .item-b
寬度強制表現為了 60px
,否則,則表現為 auto
,在這裡,則是可憐巴巴填滿剩餘的 30px
:
.item-a
.item-b
13. grid-auto-flow
grid-auto-flow
屬性控制沒有明確指定位置的grid子項的放置方式。比方說定義了一個5*2的10格子,共有5個元素,其中2個元素指定了放在哪個格子裡,還有3個則自生自滅排列。此時,這3個元素如何排列就是由 grid-auto-flow
屬性控制的。
語法如下:
.container { grid-auto-flow: row | column | row dense | column dense }
其中:
- row
- 預設值。沒有指定位置的網格依次水平排列優先。
- column
- 沒有指定位置的網格依次垂直排列優先。
- dense
- dense這個英文是稠密的意思。如果有設定,則表示自動排列啟用“密集”打包演算法。如果稍後出現的網格比較小,則嘗試看看前面有沒有合適的地方放置,使網格儘可能稠密緊湊。此屬性值僅僅改變視覺順序,會導致DOM屬性和實際呈現順序不符合,這對於可訪問性是不友好的,建議謹慎使用。
例項說話,已知CSS如下:
.container{grid-template: 1fr 1fr 1fr/1fr 2fr 2fr 1fr 2fr;} .item-a { grid-column: 1; grid-row: 2 / 4; } .item-b { grid-row: 1 / 3; } .item-c {} .item-d {} .item-e {}
也就是 .item-a
.item-b水平位置固定,點選下面單選項,體驗佈局變化。
.item-a
.item-b
.item-c
.item-d
.item-e
- 選中
row
,水平排列,此時.item-c
高度足夠放在左上角那個網格中,因此,視覺順序是c, b, d, e。 - 選中
column
,垂直排列,此時.item-c
寬度不足夠放在左上角那個網格中,因此,視覺順序(先上下後左右)是b, c, d, e。 - 選中
row dense
,水平排列,同時前面有空就鑽。視覺順序同row
屬性。 - 選中
column dense
,垂直排列,此時.item-c
放置在左上角那個網格中,因此,視覺順序(先上下後左右)是c, b, d, e,b和d垂直排列。
14. grid
語法如下:
-
grid: none
none
表示設定所有的子屬性為初始值。 -
grid: <grid-template>
和用法一致。例如這樣:
.container { grid: 100px 300px / 3fr 1fr; }
等同於下面:
.container { grid-template-rows: 100px 300px; grid-template-columns: 3fr 1fr; }
-
grid: <grid-template-rows> / [ auto-flow && dense? ] <grid-auto-columns>?
問號
?
表示0或1,可有可無的意思。也就是dense
關鍵字和grid-auto-columns
值都可以省略。具體說明:
-
auto-flow && dense?
其實就是grid-auto-flow
屬性的值,等同於row
或column
或row dense
或column dense
。但這裡
row
和column
這兩個關鍵字卻使用了auto-flow
這一個關鍵字代替了。那豈不有問題:什麼時候解析成row
,什麼時候解析成column
呢?原來,是根據
auto-flow
關鍵字是在斜槓的左側還是右側決定的。如果auto-flow
關鍵字在斜槓左側,則解析為row
,如果是在右側,則解析為column
。這裡的語法是在斜槓的右側,因此,會將grid-auto-flow
解析為column
。 -
<grid-auto-columns>
後面有個問號?
,因此是可以省略的,如果省略,則將grid-auto-columns
解析為auto
。
我們通過幾個案例學習這裡的語法:
.container { grid: 100px 300px / auto-flow 200px; }
上面CSS程式碼省略了
dense
關鍵字,啟用了<grid-auto-columns>
,因此,等同於下面CSS:.container { grid-template-rows: 100px 300px; grid-auto-flow: column; grid-auto-columns: 200px; }
記住,在Grid佈局中,斜槓前面都是rows相關屬性,斜槓後面都是columns相關屬性(下同)。
-
-
grid: [ auto-flow && dense? ] <grid-auto-rows>? / <grid-template-columns>
此語法和上面一個語法類似,只是這個斜槓前面是隱式網格,後面是顯示。在這裡,由於
auto-flow
在斜槓左側,因此解析為row
。所以:.container { grid: auto-flow dense 100px / 1fr 2fr; }
就等同於下面CSS:
.container { grid-auto-flow: row dense; grid-auto-rows: 100px; grid-template-columns: 1fr 2fr; }
grid屬性縮寫語法第一次學習會有些懵逼,乍一看,頭都大了,各種非字母以外的符號,天書一樣。其實 &
, [
, ]
, ?
這些符號實際書寫都不參與的,僅僅用來表示邏輯。
好吧,送佛送到西,我最後再給大家梳理下:
-
grid:none
好簡單好舒爽,沒什麼好說的。 - 如果網格佈局中規中矩,沒有哪個格子跑到grid容器外面,就是
grid-template
屬性。 - 最後兩個語法完全是出現了grid容器外面格子時候才使用的,要麼
grid-template/auto-flow
,要麼auto-flow/grid-template
,就這麼簡單。
說穿了,其實也沒啥,一開始使用不熟練是很正常的,你多實踐幾次,多手寫幾次,很快就能掌握,成為Grid佈局小能手了。
三、作用在grid子項上的CSS屬性
1. grid-column-start, grid-column-end, grid-row-start和grid-row-end
表示grid子項所佔據的區域的起始和終止位置,包括水平方向和垂直方向。
就好比張老闆養魚,這魚塘東邊從什麼地方開始,往西到什麼地方,南邊是哪裡,北面又到何處,都要說清楚,這樣,這魚池的面積和位置也就出來了。
語法如下:
.item { grid-column-start: <number> | <name> | span <number> | span <name> | auto grid-column-end: <number> | <name> | span <number> | span <name> | auto grid-row-start: <number> | <name> | span <number> | span <name> | auto grid-row-end: <number> | <name> | span <number> | span <name> | auto }
語法中的管道分隔符 |
表示“或者”的意思,所以別看上面好長,實際上就一個屬性值,具體來講:
- <number>
- 起止與第幾條網格線。
- <name>
- 自定義的網格線的名稱。
- span <number>
- 表示當前網格會自動跨越指定的網格數量。
- span <name>
- 表示當前網格會自動擴充套件,直到命中指定的網格線名稱。
- auto
- 全自動,包括定位,跨度等。
看例子說話,CSS和HTML如下:
.container { grid-template-columns: [第一根縱線] 80px [縱線2] auto [縱線3] 100px [最後的結束線]; grid-template-rows: [第一行開始] 25% [第一行結束] 100px [行3] auto [行末]; } .item-a { grid-column-start: 2; grid-column-end: 縱線3; grid-row-start: 第一行開始; grid-row-end: 3; }
<div class="container"> <div class="item-a"></div> </div>
實時效果如下:
number: 2
name: 縱線2
number: 1 name: 第一行開始number: 3
name: 縱線3
number: 3 name: 行3.item-a
每根網格線都有內建的 <number>
,從1開始計數,上面Grid佈局為3×3的九宮格,因此,水平和垂直都是4條網格線(含邊緣),從左往右4條線 <number>
值依次是 1-4
,垂直方向從上往下也是類似。
再本例中,所有網格線都命名了中文名稱,例如“第一根縱線”,就是最左邊豎直網格線。因此,最終效果也就不難理解了——
grid-column-start:2
表示 .item-a
網格左側起始於 <number>
為 2
的線;
grid-column-end:縱線3
表示 .item-a
網格右側結束於 <name>
為 縱線3
的線;
grid-row-start:第一行開始
表示 .item-a
網格上方開始於 <name>
為 第一行開始
的線;
grid-row-end:3
表示 .item-a
網格下方結束於 <number>
為 3
的線。
span作用表現
下面我們再來看下 span
關鍵字的作用。如下CSS和HTML:
.item-b { grid-column-start: 2; grid-column-end: span 縱線3; grid-row-start: 第一行開始; grid-row-end: span 3; }
<div class="container"> <div class="item-b"></div> </div>
效果為:
number: 2
name: 縱線2
number: 1 name: 第一行開始number: 3
name: 縱線3
number: 3 number: 4.item-b
對於命名的網格線,有 span
和沒有 span
沒有區別(包括多個同名網格線),但是,對於數值網格線,則可以看出差異,有 span
則表示跨越的個數,而非網格線的序號。例如這裡 grid-row-end:span 3
表示當前網格需要覆蓋3個格子。於是,我們可以看到 .item-b
高度貫穿整個grid容器。
2. grid-column和grid-row
grid-column
和 grid-row
都是縮寫啦,前者是+的縮寫,後者是+的縮寫。
語法上是使用斜槓分隔,如下:
.item { grid-column: <start-line> / <end-line> | <start-line> / span <value>; grid-row: <start-line> / <end-line> | <start-line> / span <value>; }
語法中的管道分隔符 |
表示“或者”的意思。然後 <start-line>
就是 grid-*-start
屬性值, <end-line>
就是 grid-*-end
屬性值。例如:
.item-b { grid-column: 2 / span 縱線3; grid-row: 第一行開始 / span 3; }
等同於:
.item-b { grid-column-start: 2; grid-column-end: span 縱線3; grid-row-start: 第一行開始; grid-row-end: span 3; }
3. grid-area
grid-area
表示當前網格所佔用的區域。在介紹屬性的時候就演示過該屬性,我們使用屬性自定義一些網格區域,然後使用 grid-area
屬性讓grid子項指定使用這些區域,就自動進行了區域分佈。
grid-area
和 grid-column/grid-row
作用都是grid子項的分佈,但 grid-area
語義要更好,識別度更佳,非常適合具有功能屬性的佈局區域(如頭部,底部),同時,還支援非規則區域。
語法如下:
.item { grid-area: <name> | <row-start> / <column-start> / <row-end> / <column-end>; }
其中:
- <name>
- <row-start> / <column-start> / <row-end> / <column-end>
- 佔據網格區域的縱橫起始位置。
<name>
屬性值使用參見上面。我們這裡演示下後面的基於位置的區域劃分,如下程式碼:
.container { grid-template: 1fr 1fr 1fr/1fr 1fr 1fr 1fr; } .item-c { grid-area: 1 / 2 / 3 / 4; }
1/2/3/4劃分區
表示水平網格線位置起止分別是1,3,垂直起止網格線位置是2,4。於是得到一個2×2大小的區域。
4. justify-self
justify-self
表示單個網格元素的水平對齊方式。語法如下:
.item { justify-self: stretch | start | end | center; }
其中(假設文件流方向沒有變):
- stretch
- 預設值,拉伸。表現為水平填充。
- start
- 表現為網格水平尺寸收縮為內容大小,同時沿著網格線左側對齊顯示。
- end
- 表現為網格水平尺寸收縮為內容大小,同時沿著網格線右側對齊顯示。
- center
- 表現為網格水平尺寸收縮為內容大小,同時在當前網格區域內部水平居中對齊顯示。
各個屬性值實時效果如下(點選單選框體驗不同屬性值佈局效果):




5. align-self
align-self
指定了網格元素的垂直呈現方式,是垂直拉伸顯示,還是上中下對齊,語法如下:
.container { align-self: stretch | start | end | center; }
其中(假設文件流方向為網頁預設):
- stretch
- 預設值,拉伸。表現為垂直填充。
- start
- 表現為網格垂直尺寸收縮為內容大小,同時沿著上網格線對齊顯示。
- end
- 表現為網格垂直尺寸收縮為內容大小,同時沿著下網格線對齊顯示。
- center
- 表現為網格垂直尺寸收縮為內容大小,同時在當前網格區域內部垂直居中對齊顯示。
各個屬性值實時效果如下(點選單選框體驗不同屬性值佈局效果):




6. place-self
place-items
可以讓 align-self
和 justify-self
屬性寫在單個宣告中。語法如下:
.container { place-items: <align-self> / <justify-self>; }
這裡順序是 align-self
在前, justify-self
在後。首字母a,j,a,j,a,j,口中不斷重複,有沒有發現跟angelababy發音很像,沒錯,記住angelababy我們也就記住這裡的順序了。
據說Edge15及之前版本尚不支援 place-self
屬性(自己未實測),因此,如果有相容性顧慮,建議還是分開書寫。
四、其他Grid知識點
- 在Grid佈局中,
float
,display:inline-block
,display:table-cell
,vertical-align
以及column-*
這些屬性和宣告對grid子項是沒有任何作用的。這個可以說是Grid佈局中的常識,面試經常會問的,一定要記得。 - Grid佈局則適用於更大規模的佈局(二維佈局),而Flexbox佈局最適合應用程式的元件和小規模佈局(一維佈局),關Flex佈局請參見“ 寫給自己看的display: flex佈局教程”一文 。
- 命名雖然支援中文,但由於CSS檔案中文存在亂碼的風險,所以……創新還是保守就看大家自己的抉擇了。
- IE10-IE15雖然名義上支援Grid佈局,但支援的是老版本語法(本文是介紹的全是2.0全新語法),還需要加
-ms-
私有字首,精力原因,IE下的使用並未深究,以後有機會再補充。
另外:
本文所有水平和垂直,左側與右側這類方位的描述均是在網頁的水平和垂直流都是預設方向前提下的表述。
本教程優點在於互動效果可以實時體驗,更直觀。如果是轉載文章,必定沒有效果,訪問原文即可。
Grid佈局自己之前並未在實際專案中使用過,本文內容也是邊學邊寫,文中若有表述不準確的地方歡迎指正。
感謝閱讀!
參考文章: A Complete Guide to Grid