使用命名網格線進行佈局

在之前的指南中,我們已經學習瞭如何將專案放置在透過定義網格軌道建立的網格線上,以及如何使用命名模板區域來放置專案。在本指南中,我們將探討當我們使用命名網格線時,這兩種方法是如何協同工作的。

網格線命名非常有用,但一些更令人困惑的網格語法恰恰來自於名稱和軌道尺寸的這種組合。一旦你完成一些示例,它應該會變得更清晰、更容易使用。

定義網格時命名網格線

當你使用 grid-template-rowsgrid-template-columns 屬性定義網格時,可以為網格中的部分或全部網格線指定一個名稱。為了演示,我們將使用在基於網格線的佈局指南中建立的基本佈局。這一次,我們將使用命名網格線來建立網格。

在定義網格時,我們在方括號([])內為網格線命名。這些名稱可以是任何你喜歡的名字。我們為容器的起始和結束線都定義了名稱,包括行和列。在這個例子中,網格中心塊的起始行和列都命名為 content-start,其結束行和列都命名為 content-end

css
.wrapper {
  display: grid;
  grid-template-columns: [main-start] 1fr [content-start] 1fr [content-end] 1fr [main-end];
  grid-template-rows: [main-start] 100px [content-start] 100px [content-end] 100px [main-end];
}

我們不必為網格中的所有網格線命名;你可以選擇只命名佈局中的關鍵網格線。

一旦網格線有了名稱,我們就可以使用我們定義的名稱,而不是行號,來放置網格專案。

css
.box1 {
  grid-column-start: main-start;
  grid-row-start: main-start;
  grid-row-end: main-end;
}

.box2 {
  grid-column-start: content-end;
  grid-row-start: main-start;
  grid-row-end: content-end;
}

.box3 {
  grid-column-start: content-start;
  grid-row-start: main-start;
}

.box4 {
  grid-column-start: content-start;
  grid-column-end: main-end;
  grid-row-start: content-end;
}
html
<div class="wrapper">
  <div class="box1">One</div>
  <div class="box2">Two</div>
  <div class="box3">Three</div>
  <div class="box4">Four</div>
</div>

基於網格線佈局的其他所有功能仍然以相同的方式工作。在我們的網格佈局中,我們為每個數字網格線提供了一個別名。在我們的網格專案中,我們引用的是名稱而不是數字。以這種方式命名網格線非常有用——在建立響應式設計時,我們可以更新容器的網格屬性,而無需在每個媒體查詢中更新網格專案。

為網格線指定多個名稱

你可能想給一條網格線多個名稱,例如,它可能同時表示側邊欄的結束(sidebar-end)和主內容的開始(main-start)。要做到這一點,請在方括號內新增名稱,並用空格隔開,如 [sidebar-end main-start]。然後你就可以透過任何一個名稱來引用該網格線。

透過命名網格線建立隱式網格區域

在命名網格線時,我們提到你可以隨意命名。這個名稱是一個 <custom-ident>,即一個由作者定義的名稱。在選擇名稱時,你需要避免使用可能出現在規範中並引起混淆的詞語——比如 span。識別符號不需要加引號。

雖然你可以選擇任何名稱,但如果你像我們上面的例子那樣,在區域周圍的網格線上附加 -start-end,網格將會建立一個以主名稱命名的區域。以上面的例子來說,我們有 content-startcontent-end,同時用於行和列。這意味著我們得到了一個名為 content 的網格區域,如果需要,我們可以將內容放置在該區域中。

我們使用與上面相同的網格定義,將一個專案放置到名為 content 的命名區域中。

css
.wrapper {
  display: grid;
  grid-template-columns: [main-start] 1fr [content-start] 1fr [content-end] 1fr [main-end];
  grid-template-rows: [main-start] 100px [content-start] 100px [content-end] 100px [main-end];
}
.thing {
  grid-area: content;
}
html
<div class="wrapper">
  <div class="thing">I am placed in an area named content.</div>
</div>

我們不需要用 grid-template-areas 來定義我們的區域,因為我們的命名網格線已經為我們建立了一個區域。

透過命名區域建立隱式網格線

我們已經看到命名網格線如何建立一個命名區域,反之亦然。命名模板區域會建立可用於放置專案的命名網格線。如果我們採用網格模板區域指南中建立的佈局,我們可以使用由區域建立的網格線來了解其工作原理。

在這個例子中,我們添加了一個額外的 <div>,其 class 為 overlay。我們使用 grid-area 屬性建立了命名區域,然後在 grid-template-areas 中建立了佈局。區域名稱是

  • hd
  • ft
  • main
  • sd

這為我們提供了以下列和行網格線

  • hd-start
  • hd-end
  • sd-start
  • sd-end
  • main-start
  • main-end
  • ft-start
  • ft-end

你可以在圖中看到這些命名的網格線。注意,有些網格線有兩個名稱——例如,sd-endmain-start 指的是同一條列網格線。

An image showing the implicit line names created by our grid areas.

使用這些隱式命名的網格線來定位 overlay 與使用顯式命名的網格線來定位專案是一樣的。

css
.wrapper {
  display: grid;
  grid-template-columns: repeat(9, 1fr);
  grid-auto-rows: minmax(100px, auto);
  grid-template-areas:
    "hd hd hd hd   hd   hd   hd   hd   hd"
    "sd sd sd main main main main main main"
    "ft ft ft ft   ft   ft   ft   ft   ft";
}

.header {
  grid-area: hd;
}

.footer {
  grid-area: ft;
}

.content {
  grid-area: main;
}

.sidebar {
  grid-area: sd;
}

.wrapper > div.overlay {
  z-index: 10;
  grid-column: main-start / main-end;
  grid-row: hd-start / ft-end;
  border: 4px solid rgb(92 148 13);
  background-color: rgb(92 148 13 / 40%);
  color: rgb(92 148 13);
  font-size: 150%;
}
html
<div class="wrapper">
  <div class="header">Header</div>
  <div class="sidebar">Sidebar</div>
  <div class="content">Content</div>
  <div class="footer">Footer</div>
  <div class="overlay">Overlay</div>
</div>

鑑於我們有能力透過命名區域建立的網格線進行定位,以及透過命名網格線建立區域,因此在開始建立網格佈局時,花點時間規劃你的命名策略是值得的。選擇對你和你的團隊有意義的名稱,將使你的佈局更加直觀。

使用 repeat() 建立多條同名網格線

如果你想給所有網格線一個唯一的名稱,你需要使用長格式屬性來定義軌道,而不是使用 repeat 語法,因為名稱需要在定義軌道時新增到方括號中。如果你確實使用了 repeat 語法,你會得到多條同名的網格線,這可能有用,也可能令人困惑,具體取決於你的佈局要求。

使用 repeat() 建立十二列網格

在這個例子中,我們建立了一個包含 12 個等寬列的網格。在定義列軌道的 1fr 大小之前,我們定義了一條名為 [col-start] 的網格線。這意味著我們將擁有一個網格,其中有 12 條都名為 col-start 的列網格線,每條線後面都跟著一個 1fr 寬度的列。

css
.wrapper {
  display: grid;
  grid-template-columns: repeat(12, [col-start] 1fr);
}

建立網格後,你可以在上面放置專案。由於我們有多條名為 col-start 的網格線,如果你將一個專案放置在 col-start 網格線之後開始,那麼將使用第一條名為 col-start 的網格線。在我們的例子中,這是最左邊的線。要指定另一條線,請使用名稱加上該線的序號。

要將一個專案放置在從第一條名為 col-start 的網格線跨越到第五條同名網格線的位置,我們可以使用

css
.item1to5 {
  grid-column: col-start / col-start 5;
}

你也可以使用 span 關鍵字。這個專案將從第七條名為 col-start 的網格線開始,跨越 3 條網格線。

css
.item7to9 {
  grid-column: col-start 7 / span 3;
}
html
<div class="wrapper">
  <div class="item1to5">I am placed from col-start line 1 to col-start 5</div>
  <div class="item7to9">I am placed from col-start line 7 spanning 3 lines</div>
</div>

如果你在瀏覽器的開發者工具中檢視這個佈局,你會看到列網格線是如何顯示的,以及我們的專案是如何根據這些網格線放置的。

The 12 column grid with items placed. The Firefox grid highlighter shows the position of the lines.

使用軌道列表定義命名網格線

repeat() 語法也可以接受一個軌道列表;它不僅僅可以重複單個軌道尺寸。

這段 CSS 建立了一個八軌道的網格,其中一個較窄的 1fr 寬度的列,其起始線名為 col1-start,後面跟著一個較寬的 3fr 寬度的列,其起始線名為 col2-start

css
.wrapper {
  grid-template-columns: repeat(4, [col1-start] 1fr [col2-start] 3fr);
}

如果你的重複語法將兩條線放在一起,那麼它們將被合併,併產生與在非重複軌道定義中為一條線指定多個名稱相同的結果。以下定義建立了四個 1fr 的軌道,每個軌道都有一個起始線和一個結束線。

css
.wrapper {
  grid-template-columns: repeat(4, [col-start] 1fr [col-end]);
}

如果我們不使用 repeat 寫法,這個宣告看起來是這樣的

css
.wrapper {
  grid-template-columns: [col-start] 1fr [col-end col-start] 1fr [col-end col-start] 1fr [col-end col-start] 1fr [col-end];
}

使用軌道列表,我們可以使用 span 關鍵字來跨越一定數量的網格線,包括特定名稱的網格線。

css
.wrapper {
  display: grid;
  grid-template-columns: repeat(6, [col1-start] 1fr [col2-start] 3fr);
}

.item1 {
  grid-column: col1-start / col2-start 2;
}

.item2 {
  grid-row: 2;
  grid-column: col1-start 2 / span 2 col1-start;
}
html
<div class="wrapper">
  <div class="item1">
    I am placed from col1-start line 1 to col2-start line 2
  </div>
  <div class="item2">
    I am placed from col1-start line 2 spanning 2 lines named col1-start
  </div>
</div>

十二列網格框架

在學習了基於數字和命名的網格線佈局以及網格模板區域之後,我們現在知道有多種方法可以使用 CSS 網格佈局來放置專案。這可能看起來過於複雜,但你不需要全部使用它們。在實踐中,使用命名模板區域對於簡單的佈局效果很好,因為這種方法能很好地在視覺上呈現你的佈局是什麼樣子,並使在網格上移動內容變得更加直觀。例如,在處理嚴格的多列布局時,本指南最後一部分演示的命名網格線就很好用。

像 Foundation 或 Bootstrap 這樣的傳統網格系統是基於 12 列網格的。這些框架需要引入程式碼來進行計算,以確保列的總和達到 100%。但其實並不需要框架!我們只需要以下 CSS 就可以建立一個 12 列網格“框架”:

css
.wrapper {
  display: grid;
  gap: 10px;
  grid-template-columns: repeat(12, [col-start] 1fr);
}

然後我們可以使用這個“框架”來佈局我們的頁面。

例如,要建立一個帶有頁首和頁尾的三列布局,我們可以使用以下標記。

html
<div class="wrapper">
  <header class="main-header">I am the header</header>
  <aside class="side1">I am sidebar 1</aside>
  <article class="content">I am the main article</article>
  <aside class="side2">I am sidebar 2</aside>
  <footer class="main-footer">I am the footer</footer>
</div>

我們可以將其放置在我們的網格佈局框架上

css
.main-header,
.main-footer {
  grid-column: col-start / span 12;
}

.side1 {
  grid-column: col-start / span 3;
  grid-row: 2;
}

.content {
  grid-column: col-start 4 / span 6;
  grid-row: 2;
}

.side2 {
  grid-column: col-start 10 / span 3;
  grid-row: 2;
}

再次強調,開發者工具的網格高亮器有助於向我們展示我們放置專案的網格是如何工作的。

The layout with the grid highlighted.

這就是我們所需要的全部。我們不需要做任何計算!CSS 網格佈局在為 1fr 列軌道分配空間之前,自動減去了我們 10 畫素的間距軌道。

接下來,我們將探討 CSS 網格佈局如何在完全不需要放置屬性的情況下為我們定位專案,詳見網格佈局中的自動放置指南。