原文連接:Understanding CSS Grid: Grid Template Areas,by Rachel Andrewjavascript
本文是講解網格佈局系列的第三篇,教你從網格佈局新手到專家。css
咱們已經學瞭如何使用行號和命名網格線定位網格項目。其實還有一種定位網格項目的方式,它是對佈局的天然描述——grid-template-areas
屬性。本篇文章介紹如何使用 grid-template-areas
屬性,以及它的工做原理。html
grid-template-areas
描述佈局grid-template-areas
屬性接收由一個或多個字符串組成的值。每一個字符串(包圍在引號中)表明網格里的一行。它能夠在已經設置了 grid-template-columns
屬性(grid-template-rows
有無設置皆可)的網格上使用。java
下例中的網格,用了四個區域描述,每一個區域佔據兩行兩列。網格區域是經過在多個單元格重複某個區域名稱來劃定範圍的。bash
grid-template-areas: "one one two two"
"one one two two"
"three three four four"
"three three four four";
複製代碼
在網格項目上使用 grid-area
屬性,爲其指定某個區域名稱,即表示這個區域被該項目佔據了。假設,有一個 .test
項目想要佔據叫 one
的這個區域,能夠這樣指定:app
.test {
grid-area: one;
}
複製代碼
下面是一個完整的例子:ide
<div class="grid">
<div class="one">1</div>
<div class="two">2</div>
<div class="three">3</div>
<div class="four">4</div>
</div>
<style> .grid { display: grid; grid-template-areas: "one one two two" "one one two two" "three three four four" "three three four four"; grid-template-columns: repeat(4, 1fr); grid-template-rows: repeat(4, 100px); } .one { grid-area: one; } .two { grid-area: two; } .three { grid-area: three; } .four { grid-area: four; } </style>
複製代碼
效果(demo):佈局
若是使用 Firefox Grid Inspector 查看區域名稱和行號分佈,會看見每一個項目但都佔據了兩行兩列,在網格中獲得定位。post
grid-template-areas
的規則使用 grid-template-areas
屬性有一些限定規則,若是打破規則,佈局也就無效了。第一個規則是 你必需要完整描述網格,即要考慮網格里的每一個單元格。ui
若是某個單元格須要留空,就必須插入一個或多個點(好比 .
或 ...
等均可以)佔位。注意在使用多個點時,點與點之間是沒有空格的。
因此,還能夠這樣定義:
grid-template-areas: "one one two two"
"one one two two"
". . four four"
"three three four four";
複製代碼
效果(demo):
一個區域名不能在不連續的兩塊區域上使用。好比,下面的定義 three
的方式就是無效的:
grid-template-areas: "one one three three"
"one one two two"
"three three four four"
"three three four four";
複製代碼
另外,不能建立一個非矩形區域。好比,「L」或「T」形區域的定義是無效的。
grid-template-areas: "one one two two"
"one one one one"
"three three four four"
"three three four four";
複製代碼
我喜歡用上面的方式來定義 grid-template-areas
屬性——每一行字符串對應網格里的一行,看起來很直觀。
有時爲了達到列與列之間的對齊效果,我會選擇使用多個點來指定空單元格。
grid-template-areas: "one one two two"
"one one two two"
"..... ..... four four"
"three three four four";
複製代碼
固然,字符串排列在一行也是有效的:
grid-template-areas: "one one two two" "one one two two" "three three four four" "three three four four";
複製代碼
grid-template-areas
和 grid-area
之因此每塊命名區域都要保持爲矩形,是由於每塊區域都要求能用基於網格線方式實現——而使用四根網格線定義的區域必然是個矩形,不會是個非矩形。
我先舉一個使用網格線定位項目的例子:
<div class="grid">
<div class="item">Item</div>
</div>
<style> .grid { display: grid; grid-template-columns: repeat(5, 100px); grid-template-rows: repeat(5, 50px); } .item { grid-column: 2 / 4; grid-row: 1 / 4; } </style>
複製代碼
效果(demo):
就是說,只要爲一個項目指定了下面四個屬性就能準肯定位它在網格中的位置了:
grid-row-start
grid-column-start
grid-row-end
grid-column-end
而 grid-area
屬性剛好支持以這種順序指定項目位置的語法:
grid-area: grid-row-start grid-column-start grid-row-end grid-column-end
複製代碼
所以,下面的寫法:
.grid {
grid-template-areas: "one one two two"
"one one two two"
"three three four four";
"three three four four";
}
.one {
grid-area: one;
}
.two {
grid-area: two;
}
.three {
grid-area: three;
}
.four {
grid-area: four;
}
複製代碼
能夠改寫成:
.one {
grid-area: 1 / 1 / 3 / 3;
}
.two {
grid-area: 1 / 3 / 3 / 5;
}
.three {
grid-area: 3 / 1 / 5 / 3;
}
.four {
grid-area: 3 / 3 / 5 / 5;
}
複製代碼
grid-area
有趣的地方在於還可以使用行號和命名網格線的方式,爲項目指定定位區域。
grid-area
上面講的是使用 4 個行號來指定 grid-area
屬性。可是,若是不是 4 個呢?——好比,我只指定了前三個,沒有指定第 4 個值——這時,會使用缺省值 auto
,也就是默認延伸一個軌道。所以,若是爲一個項目使用的是 grid-row-start: 3
,就是說其餘三個值都設置成 auto
了——此時項目默認佔據一行一列:
.item { grid-area: 3; }
複製代碼
效果:
「indent」是對網格中 命名區域 的稱呼。
下面我舉了一個使用命名網格線指定 grid-area
屬性的例子。
.grid {
display: grid;
grid-template-columns:
[one-start three-start] 1fr 1fr
[one-end three-end two-start four-start] 1fr 1fr [two-end four-end];
grid-template-rows:
[one-start two-start] 100px 100px
[one-end two-end three-start four-start] 100px 100px [three-end four-end];;
}
.two {
grid-area: two-start / two-start / two-end;
}
複製代碼
注意到,這裏我並未指定 grid-column-end
這個值。規範提到,在這種狀況下,grid-column-end
的值就複製 grid-column-start
的,而在 grid-column-end
與 grid-column-start
同樣的狀況下,grid-column-end
值又會被丟棄,最後的結果與設置行號時同樣了——等同於設置了 auto
——自動延伸一個軌道。
還有,若是缺失的是第三個屬性 grid-row-end
的值,它也是先複製 grid-row-start
的值,最後等同於設置 auto
。
下面舉了一個比較全面的例子,列出了全部的狀況:
<div class="grid">
<div class="one">1</div>
<div class="two">2</div>
<div class="three">3</div>
<div class="four">4</div>
</div>
<style> .grid { display: grid; grid-template-columns: [one-start three-start] 1fr 1fr [one-end three-end two-start four-start] 1fr 1fr [two-end four-end]; grid-template-rows: [one-start two-start] 100px 100px [one-end two-end three-start four-start] 100px 100px [three-end four-end]; } .one { grid-area: one-start / one-start / one-end / one-end; } .two { grid-area: two-start / two-start / two-end; } .three { grid-area: three-start / three-start; } .four { grid-area: four-start; } </style>
複製代碼
效果(demo):
這也能解釋了爲何再給 grid-area
僅設置一個 ident 值的狀況下也能正常工做的原理(實際拓展成 4 個值的寫法了)。
還有一點你們須要知道的是,使用 grid-template-areas
屬性建立命名區域的時候,每塊區域的邊緣網格線均可以使用區域名稱引用。我以一個叫 one
的區域名稱舉例。
下面的寫法,
.one {
grid-area: one;
}
複製代碼
等同於這種(其餘三個值複製第一個值):
.one {
grid-row-start: one;
grid-row-end: one;
grid-column-start: one;
grid-row-end: one;
}
複製代碼
若是是 -star
t 屬性,那麼 one
會被解析到這塊區域行、列的起始線;若是是 -end
屬性,那麼 one
就會解析到這塊區域行、列的終止線。固然,這種狀況僅適應於 grid-area
使用一個命名區域值指定的場景。
grid-template-areas
的佈局中層疊項目使用 grid-template-areas
定義區域的時候,每一個單元格能且只能對應一個名稱。固然,在完成主體佈局以後,你仍然可使用行號向佈局中疊加新的項目。
下例中,在主題佈局以外,我基於網格線在佈局中疊加了一個項目:
<div class="grid">
<div class="one">1</div>
<div class="two">2</div>
<div class="three">3</div>
<div class="four">4</div>
<div class="five">5</div>
</div>
<style>
.grid {
display: grid;
grid-template-areas:
"one one two two"
"one one two two"
"three three four four"
"three three four four";
grid-template-columns: repeat(4, 1fr);
grid-template-rows: repeat(4, 100px);
}
.one {
grid-area: one;
}
.two {
grid-area: two;
}
.three {
grid-area: three;
}
.four {
grid-area: four;
}
/* 與前面不一樣的是,這個項目是使用行號定位的 */
.five {
grid-row: 2 / 4;
grid-column: 2 / 4;
}
</style>
複製代碼
效果(demo):
你還可使用命名網格線來指定項目佔據的行和列。更好的是,在使用 grid-template-areas
定義網格區域的時候,實際上也會同時給區域周圍的四根網格線生成一個以區域名爲前綴的名字,區域起始邊緣的網格線的名稱是 xx-start
的形式,終止邊緣的的網格線的名稱則是 xx-end
的形式。
以命名區域 one
爲例,它的起始邊線名字叫 one-start
,終止邊線的名字則叫 one-end
。
網格中,你可使用這些隱式生成的命名網格線定位項目。這在須要不一樣的斷點處從新定義網格佈局的場景中,你但願某個定位項目始終位於某個行名以後,會頗有用。
<div class="grid">
<div class="one">1</div>
<div class="two">2</div>
<div class="three">3</div>
<div class="four">4</div>
<div class="five">5</div>
</div>
<style> .grid { display: grid; grid-template-areas: "one one two two" "one one two two" "three three four four" "three three four four"; grid-template-columns: repeat(4, 1fr); grid-template-rows: repeat(4, 100px); } .one { grid-area: one; } .two { grid-area: two; } .three { grid-area: three; } .four { grid-area: four; } .five { grid-row: one-start / three-end; grid-column: three-start / four-start; } </style>
複製代碼
效果(demo):
grid-template-areas
我在構建組件庫的時候,發使用 grid-template-areas
屬性能夠很準確的從 CSS 裏看到組件組成方式。特別是在不一樣斷點處從新定義網格佈局的時候,我只要給 grid-template-areas
屬性從新賦值,就能改變當前網格里軌道數量和區域分佈。
在下面的 CSS 中,默認組件是單列布局的,在視口寬度達到 600px
以上時,我會從新給 grid-template-area
屬性賦值,改變成兩列布局。這種方法的好處(也是我前面說過的)就是任何看到這段 CSS 的人均可很清晰看懂是如何佈局的。
.wrapper {
background-color: #fff;
padding: 1em;
display: grid;
gap: 20px;
grid-template-areas:
"hd"
"bd"
"sd"
"ft";
}
@media (min-width: 600px) {
.wrapper {
grid-template-columns: 3fr 1fr;
grid-template-areas:
"hd hd"
"bd sd"
"ft ft";
}
}
header { grid-area: hd; }
article {grid-area: bd; }
aside { grid-area: sd; }
footer { grid-area: ft; }
複製代碼
使用 grid-template-areas
和 grid-area
屬性定義佈局的方式,可能會帶來的一個問題就是 元素的視覺呈現跟在源碼的順序多是不一致的。若是是使用 Tab 按鍵或語言助手訪問的頁面,那麼看到或聽到的內容是按照源碼順序來的,若是佈局裏的元素由於詩視覺須要移動了位置,那麼就會致使視覺呈現上的混亂。因此,在移動項目的時候,必定要留意視覺呈現與源碼上的關聯性,不至於使用輔助設備訪問時,獲得不一致的體驗。
以上是使用 grid-template-area
和 grid-area
屬性建立佈局的所有內容。 若是你還沒使用過這種佈局方式的話,能夠嘗試一下。我發現使用這種佈局方式設計原型頁面很是方便。
(正文完)
廣告時間(長期有效)
我有一位好朋友開了一間貓舍,在此幫她宣傳一下。如今貓舍裏養的都是布偶貓。若是你也是個愛貓人士而且有須要的話,不妨掃一掃她的【閒魚】二維碼。不買也沒關係,看看也行。
(完)