[譯] 理解 CSS 網格佈局:網格區域

原文連接: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):佈局

image.png

若是使用 Firefox Grid Inspector 查看區域名稱和行號分佈,會看見每一個項目但都佔據了兩行兩列,在網格中獲得定位。post

image.png

使用 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):

image.png

一個區域名不能在不連續的兩塊區域上使用。好比,下面的定義 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):

image.png

就是說,只要爲一個項目指定了下面四個屬性就能準肯定位它在網格中的位置了:

  • 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; }
複製代碼

效果:

image.png

使用 indent 的 grid-area

「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-endgrid-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):

image.png

這也能解釋了爲何再給 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;
}
複製代碼

若是是 -start 屬性,那麼 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):

image.png

你還可使用命名網格線來指定項目佔據的行和列。更好的是,在使用 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):

image.png

在響應式設計中使用 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-areagrid-area 屬性建立佈局的所有內容。 若是你還沒使用過這種佈局方式的話,能夠嘗試一下。我發現使用這種佈局方式設計原型頁面很是方便。

(正文完)


廣告時間(長期有效)

我有一位好朋友開了一間貓舍,在此幫她宣傳一下。如今貓舍裏養的都是布偶貓。若是你也是個愛貓人士而且有須要的話,不妨掃一掃她的【閒魚】二維碼。不買也沒關係,看看也行。

(完)

相關文章
相關標籤/搜索