格線

CSS Podcast - 011:格線

網頁設計中非常常見的版面配置是頁首、側欄、內文和頁尾版面配置。

標頭包含標誌和導覽列,側欄和內容區域則顯示文章

多年來,解決這個版面配置問題的方法有很多,但使用 CSS 格線不僅相對簡單,而且有很多選項。Grid 非常適合用於結合外在大小控制和內在大小彈性,因此是這類版面配置的理想選擇。這是因為格線是專為二維內容設計的版面配置方法。也就是同時以列和欄的方式排列項目。

建立格線版面配置時,請定義含有列和欄的格線。 然後將項目放置到格線中, 或允許瀏覽器將項目自動放置到您建立的儲存格中。 格線的內容很多, 但只要瞭解可用的項目, 很快就能製作格線版面配置。

總覽

那麼格線可以做什麼?格狀版面配置具有下列功能。 本指南將說明所有這些功能。

  1. 網格可透過列和欄定義。您可以選擇如何調整這些列和欄的軌道大小,也可以讓這些軌道根據內容大小調整。
  2. 格線容器的直接子項會自動放置在這個格線上。
  3. 或者,你也可以將項目放在想要的位置。
  4. 您可以為格線上的線條和區域命名,方便放置項目。
  5. 格線容器中的剩餘空間可分配給軌道。
  6. 格線項目可以在所屬區域內對齊。

格線術語

Grid 帶來許多新詞彙,因為這是 CSS 首次擁有真正的版面配置系統。

格線

格線由水平和垂直線組成。如果格線有四欄,就會有五條欄線,包括最後一欄後方的欄線。

行號從 1 開始,編號方式會依據元件的書寫模式和文字方向。 也就是說,如果是英文這類由左至右的語言,第 1 欄線會位於左側;如果是阿拉伯文這類由右至左的語言,第 1 欄線則會位於右側。

格線的表示法

格線軌

軌道是指兩條格線之間的空間。 列軌介於兩條列線之間,欄軌則介於兩條欄線之間。 建立格線時,我們會為這些軌指派大小,藉此建立軌。

格線軌道的表示法

網格

格線儲存格是格線上最小的空間,由資料列和資料欄軌的交集定義。 就像表格儲存格或試算表中的儲存格。 如果您定義格線,但未放置任何項目,系統會自動將每個項目放置到定義的格線儲存格中。

格線儲存格的表示法

格線區域

多個格線儲存格。如要建立格線區域,請讓項目跨越多個軌道。

格線區域的表示法

落差

軌道間的溝渠或巷道。 就大小調整而言,這些軌道的作用與一般軌道相同。 你無法將內容放入間距,但可以讓格線項目跨越間距。

有間隔的格線表示法

格線容器

套用 display: grid 的 HTML 元素,因此會為直接子項建立新的格線格式化環境。

.container {
  display: grid;
}

格線項目

格線項目是指格線容器的直接子項。

<div class="container">
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
</div>

列和欄

如要建立基本格線,可以定義具有三個欄軌、兩個列軌,以及軌道間 10 像素間距的格線,如下所示。

.container {
    display: grid;
    grid-template-columns: 5em 100px 30%;
    grid-template-rows: 200px auto;
    gap: 10px;
}

這個格線展示了術語部分所述的許多內容。 其中有三個欄軌。 每個軌道使用的長度單位都不相同。 這個範例有兩個列軌,一個使用長度單位,另一個則為自動。當做軌道大小使用時,auto 可以視為與內容一樣大。軌道預設會自動調整大小。

如果具有 .container 類別的元素有子項,這些子項會立即在這個格線中版面配置。您可以在下列試用版中查看實際運作情形:

Chrome 開發人員工具中的格線疊加層可協助您瞭解格線的各個部分。

在 Chrome 中開啟試用版。 檢查 ID 為 container 的灰色背景元素。 在 DOM 中選取 .container 元素旁邊的格線徽章,即可醒目顯示格線。 在「版面配置」分頁的「重疊顯示設定」下方,選取下拉式選單中的「顯示行號」,即可在格線中查看行號。

如說明文字和操作說明所述
Chrome 開發人員工具中醒目顯示的格線,顯示行號、儲存格和軌跡。

內建大小調整關鍵字

除了大小單位一節所述的長度和百分比維度,格線軌也可以使用內建大小關鍵字。這些關鍵字定義於 Box Sizing 規格,並在 CSS 中新增其他方塊大小調整方法,而不只是格線軌。

  • min-content
  • max-content
  • fit-content()

min-content 關鍵字會將軌道縮到最小,但不會溢出軌道內容。將範例格線版面配置變更為三個資料欄軌,且大小皆為 min-content,表示這些資料欄會縮窄至軌中最長字詞的寬度。

max-content 關鍵字的效果則相反。軌道會變寬,足以顯示所有內容,形成一長串不間斷的字串。 這可能會導致溢位,因為字串不會換行。

fit-content() 函式一開始的行為與 max-content 類似。 不過,一旦軌道達到您傳遞至函式的大小,內容就會開始換行。因此,如果 max-content 大小小於 10em,fit-content(10em) 會建立小於 10em 的軌道,但絕不會大於 10em。

在下一個範例中,請變更格線軌的大小,試試不同的內建大小關鍵字。

fr 單位

我們有現有的長度維度、百分比,以及這些新關鍵字。 此外,還有一個特殊的大小調整方法,僅適用於格線版面配置。 這是 fr 單位,屬於彈性長度,用於描述格狀容器中可用空間的比例。

fr 單位的運作方式與在彈性方塊中使用 flex: auto 類似。 在項目版面配置完成後,分配項目間的空間。 因此,如要讓三個資料欄平均分配可用空間,請按照下列步驟操作:

.container {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
}

由於 fr 單位會分享可用空間,因此可以與固定大小的間隙或固定大小的軌道合併。如要讓元件包含大小固定的元素,並讓第二個軌道佔用剩餘空間,您可以將 grid-template-columns: 200px 1fr 用做軌道清單。

使用不同的 fr 單位值,即可按比例共用空間。 數值越大,可用的備用空間就越多。 在下列試用版中,變更第三個音軌的值。

minmax() 函式

Browser Support

  • Chrome: 57.
  • Edge: 16.
  • Firefox: 52.
  • Safari: 10.1.

Source

這項函式表示你可以為軌道設定大小下限和上限。 這項功能相當實用。 以分配剩餘空間的 fr 單位為例,可以使用 minmax() 寫成 minmax(auto, 1fr)。Grid 會查看內容的內在大小,然後在提供足夠空間給內容後,分配可用空間。也就是說,您可能無法取得在格線容器中平均分配所有可用空間的軌道。

如要強制軌道在格線容器中佔用等量的空間 (扣除間隙),請使用 minmax。 將 1fr 替換為 minmax(0, 1fr),做為軌道大小。這會將軌道的最小大小設為 0,而非最小內容大小。然後,格線會使用容器中的所有可用大小,扣除任何間隙所需的大小,並根據 fr 單位分享其餘大小。

repeat() 標記

Browser Support

  • Chrome: 57.
  • Edge: 16.
  • Firefox: 76.
  • Safari: 10.1.

Source

如要建立 12 欄的軌格,且各欄寬度相同,可以使用下列 CSS。

.container {
    display: grid;
    grid-template-columns:
      minmax(0,1fr),
      minmax(0,1fr),
      minmax(0,1fr),
      minmax(0,1fr),
      minmax(0,1fr),
      minmax(0,1fr),
      minmax(0,1fr),
      minmax(0,1fr),
      minmax(0,1fr),
      minmax(0,1fr),
      minmax(0,1fr),
      minmax(0,1fr);
}

或者,您也可以使用 repeat() 寫出:

.container {
    display: grid;
    grid-template-columns: repeat(12, minmax(0,1fr));
}

repeat() 函式可用來重複播放曲目清單的任何部分。 舉例來說,你可以重複播放特定曲目。 你也可以使用一些一般音軌和重複的章節。

.container {
    display: grid;
    grid-template-columns: 200px repeat(2, 1fr 2fr) 200px; /*creates 6 tracks*/
}

auto-fillauto-fit

您可以結合所學的軌道大小、minmax() 和重複功能,使用格線版面配置建立實用模式。您可能不想指定欄軌數量,而是想建立盡可能多的欄軌,以填滿容器。

您可以使用 repeat()auto-fillauto-fit 關鍵字達成此目的。 在下列範例中,格線會建立盡可能多的 200 像素軌,以填滿容器。在新視窗中開啟示範,並在變更可視區域大小時,查看格線的變化。

在試用版中,我們盡可能提供最多曲目。 不過,這些軌道並不具彈性。 直到有足夠空間容納另一個 200 像素的軌道為止,結尾都會出現間隙。 如果加入 minmax() 函式,您可要求盡可能多的軌道,但最小尺寸為 200 像素,最大尺寸為 1fr。然後格線會配置 200 像素的軌道,並將剩餘空間平均分配給這些軌道。

這樣一來,您就能建立二維回應式版面配置,完全不需要任何媒體查詢。

auto-fillauto-fit 之間有細微差異。 在下一個示範中,請使用先前說明的語法,但格線容器中只有兩個格線項目,並使用格線版面配置。使用 auto-fill 關鍵字,您會發現已建立空白軌。 將關鍵字變更為 auto-fit,並將軌道摺疊為 0 大小。 也就是說,彈性軌道現在會擴展以填滿空間。

auto-fillauto-fit 關鍵字的其他作用完全相同。 填滿第一條音軌後,兩者就沒有差異。

自動設定廣告插播時間點

在目前為止的示範中,您已看過格線自動放置功能。系統會按照項目在來源中的顯示順序,將項目放置在格線的每個儲存格中。對許多版面配置來說,這樣就夠了。如要進一步控管,可以採取下列幾種做法。 首先,調整自動刊登位置的版面配置。

將項目放在資料欄中

格線版面配置的預設行為是將項目放置在列中。您可以改用 grid-auto-flow: column,讓項目放置在欄中。 您必須定義資料列軌,否則項目會建立內建的資料欄軌,並將所有項目排成一長列。

這些值與文件的書寫模式有關。 資料列一律會以句子在文件或元件的書寫模式中執行的方向執行。 在下一個示範中,您可以變更 grid-auto-flow 的值和 writing-mode 屬性。

跨軌

您可以讓自動放置的版面配置中的部分或所有項目跨越多個軌道。使用 span 關鍵字,加上要跨越的行數,做為 grid-column-endgrid-row-end 的值。

.item {
    grid-column-end: span 2; /* will span two lines, therefore covering two tracks */
}

由於您未指定 grid-column-start,因此系統會使用 auto 的初始值,並根據自動刊登位置規則放置廣告。您也可以使用簡寫 grid-column 指定相同內容:

.item {
    grid-column: auto / span 2;
}

填補落差

如果自動放置的版面配置中,部分項目跨越多個軌道,可能會導致格線出現未填滿的儲存格。完全自動放置的格線版面配置預設行為一律是向前推進。項目會按照來源中的順序放置,或根據 order 屬性進行任何修改。如果空間不足以容納項目,格線會留下間隙,並移至下一個軌道。

下一個範例會顯示這項行為。 勾選這個核取方塊即可套用密集封裝模式。 如要啟用這項功能,請將 grid-auto-flow 的值設為 dense。有了這個值,格線稍後就會在版面配置中取得項目,並用來填補間隙。這可能表示顯示畫面會與邏輯順序中斷連線。

放置物品

您已經擁有許多 CSS 格線功能。 現在,請看看如何在我們建立的格線中放置項目。

首先要記住,CSS 格線版面配置是以編號格線為基礎。將項目放置到格線最簡單的方法,就是從一行放置到另一行。本指南會介紹其他放置項目的方式,但您隨時可以存取這些編號行。

您可以用來依行號放置項目的屬性如下:

這些簡寫可讓你一次設定開始和結束行:

如要放置項目,請設定要放置項目的格線區域的開始和結束線。

.container {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    grid-template-rows: repeat(2, 200px 100px);
}

.item {
    grid-column-start: 1; /* start at column line 1 */
    grid-column-end: 4; /* end at column line 4 */
    grid-row-start: 2; /*start at row line 2 */
    grid-row-end: 4; /* end at row line 4 */
}

Chrome 開發人員工具會提供線條的視覺化指南,方便您檢查項目放置位置。

行號會依據元件的書寫模式和方向顯示。 在下一個範例中,變更書寫模式或方向,看看項目位置如何與文字流動方式保持一致。

堆疊項目

使用以線條為準的定位方式,您可以將項目放在格線的同一個儲存格中。 也就是說,您可以堆疊項目,或讓一個項目部分重疊另一個項目。來源中較晚出現的項目會顯示在較早出現的項目上方。 您可以使用 z-index 變更這個堆疊順序,就像處理已定位的項目一樣。

負數行號

使用 grid-template-rowsgrid-template-columns 建立格線時,您會建立所謂的「明確格線」。這是您定義的格線,並為軌道指定大小。

有時項目會顯示在這個明確格線之外。 舉例來說,您可以定義欄軌,然後新增多列格線項目,但完全不定義列軌。根據預設,系統會自動調整軌道大小。 您也可以使用 grid-column-end 將項目放置在明確定義的格線之外。在這兩種情況下,格線都會建立軌道來運作版面配置,這些軌道稱為「隱含格線」

無論使用隱含或明確格線,通常都不會有任何差異。 不過,使用以行做為基準的刊登位置時,您可能會遇到兩者之間的主要差異。

您可以使用負數行號,從明確格線的結尾行放置項目。 如果您希望項目橫跨第一個和最後一個資料欄線,這項功能就非常實用。 在這種情況下,您可以使用 grid-column: 1 / -1。 項目會向右延伸,跨越明確格線。

但這只適用於明確格線。 假設您要讓自動放置項目的三列版面配置中,第一個項目跨越格線的尾端。

側邊欄,內含 8 個同層級的格線項目

您可能會認為可以將該項目設為 grid-row: 1 / -1。 在下列範例中,您會發現這項功能無法運作。 系統會在隱含格線中建立軌道,因此無法使用 -1 抵達格線結尾。

隱含軌道大小

隱含格線中建立的軌道預設會自動調整大小。 不過,如要控制列的大小,請使用 grid-auto-rows 屬性,欄則使用 grid-auto-columns

如要建立所有隱含列,且最小尺寸為 10em,最大尺寸為 auto,請使用下列程式碼:

.container {
    display: grid;
    grid-auto-rows: minmax(10em, auto);
}

如要建立隱含欄,且軌道寬度模式為 100 像素和 200 像素,請執行下列操作:在這種情況下,第一個隱含資料欄會是 100 像素、第二個是 200 像素、第三個是 100 像素,依此類推。

.container {
    display: grid;
    grid-auto-columns: 100px 200px;
}

已命名的格線

如果線條有名稱而非數字,將項目放入版面配置會更容易。 您可以在方括號之間加入所選名稱,為格線上的任何線條命名。 您可以在同一組方括號內新增多個名稱,並以空格分隔。 命名線條後,即可使用名稱代替數字。

.container {
    display: grid;
    grid-template-columns:
      [main-start aside-start] 1fr
      [aside-end content-start] 2fr
      [content-end main-end]; /* a two column layout */
}

.sidebar {
    grid-column: aside-start / aside-end;
    /* placed between line 1 and 2*/
}

footer {
    grid-column: main-start / main-end;
    /* right across the layout from line 1 to line 3*/
}

格線範本區域

您也可以為格線區域命名,並將項目放置在這些命名區域上。 這項技術很實用,因為您可以在 CSS 中直接查看元件的外觀。

首先,請使用 grid-area 屬性為格線容器的直接子項命名:

header {
    grid-area: header;
}

.sidebar {
    grid-area: sidebar;
}

.content {
    grid-area: content;
}

footer {
    grid-area: footer;
}

名稱可以是任何內容,但不能是 autospan 關鍵字。 為所有項目命名後,請使用 grid-template-areas 屬性定義每個項目跨越的格線儲存格。每列都以引號括住。

.container {
    display: grid;
    grid-template-columns: repeat(4,1fr);
    grid-template-areas:
        "header header header header"
        "sidebar content content content"
        "sidebar footer footer footer";
}

使用 grid-template-areas 時須遵守幾項規則。

  • 這個值必須是完整的格線,不得有空白儲存格。
  • 如要跨軌,請重複名稱。
  • 重複名稱建立的區域必須是矩形,且不得中斷。

如果違反上述任何規則,系統會將值視為無效並捨棄。

如要在格線中留白,請使用 . 或多個 .,且之間不得有空白。 舉例來說,如要將格線上的第一個儲存格留空,可以新增一連串的 . 字元:

.container {
    display: grid;
    grid-template-columns: repeat(4,1fr);
    grid-template-areas:
        "....... header header header"
        "sidebar content content content"
        "sidebar footer footer footer";
}

由於整個版面配置都是在同一個位置定義,因此使用媒體查詢重新定義版面配置非常簡單。在下一個範例中,我建立了一個雙欄版面配置,並重新定義 grid-template-columnsgrid-template-areas 的值,將版面配置移至三欄。 在新視窗中開啟範例,調整可視區域大小,看看版面配置的變化。

您也可以查看 grid-template-areas 屬性與 writing-mode 和方向的關係, 就像其他格線方法一樣。

簡寫屬性

有兩項簡寫屬性可讓您一次設定多項格線屬性。只要瞭解這些屬性的搭配方式,就不會覺得混淆。你可以選擇是否要使用縮寫。

grid-template

Browser Support

  • Chrome: 57.
  • Edge: 16.
  • Firefox: 52.
  • Safari: 10.1.

Source

grid-template 屬性是 grid-template-rowsgrid-template-columnsgrid-template-areas 的簡寫。 首先定義資料列,以及 grid-template-areas 的值。在 / 後方新增資料欄大小。

.container {
    display: grid;
    grid-template:
      "head head head" minmax(150px, auto)
      "sidebar content content" auto
      "sidebar footer footer" auto / 1fr 1fr 1fr;
}

grid 資源

Browser Support

  • Chrome: 57.
  • Edge: 16.
  • Firefox: 52.
  • Safari: 10.1.

Source

grid 速記與 grid-template 速記的使用方式完全相同。 以這種方式使用時,系統會將接受的其他格線屬性重設為初始值。 完整設定如下:

  • grid-template-rows
  • grid-template-columns
  • grid-template-areas
  • grid-auto-rows
  • grid-auto-columns
  • grid-auto-flow

您也可以使用這個簡寫,定義隱含格線的行為,例如:

.container {
    display: grid;
    grid: repeat(2, 80px) / auto-flow  120px;
}

子格線

只要加入 display: grid,任何格線項目都可以成為自己的格線容器。 根據預設,這個巢狀格線有自己的軌道大小,與父項格線分開。使用子格線時,子格線容器會從父格線繼承軌道大小、行名稱和間距,因此使用共用格線時,更容易對齊項目。

如要在巢狀格線中使用父項的格線欄,請設定 grid-template-columns: subgrid。如要在巢狀格線中使用父項的格線列,請設定 grid-template-rows: subgrid。您也可以使用 subgrid 調整列和欄。

在下列範例中,有一個類別為 gallery 的格線,其中包含幾個彈性欄。由於沒有 grid-template-rows 定義,因此列大小來自內容。圖片庫中的格線項目也是格線容器,設定為從下一個可用資料列 (auto) 開始,並跨越兩個軌道。最後,grid-template-rows 屬性會使用子格線,讓不同的 gallery-item 格線共用相同的格線軌大小。如果註解掉這行,就會發現說明文字不再對齊。

將子格線套用至欄和列

將子格套用至列和欄時,子格會在兩個維度中使用父項的格線軌。在下列程式碼片段中,有一個明確的格線,包含四個欄和四個列,且軌道大小不同。

.container {
  display: grid;
  gap: 1em;
  grid-template-columns: auto 2fr 1fr auto;
  grid-template-rows: 5fr 1fr 2fr 1fr;
}

其中一個格線項目也包含 display: grid,且設為跨越父項格線的兩欄和三列。加入 subgrid 值之前,巢狀格線中的項目不會與父項格線中的格線項目對齊。

.subgrid-container {
  display: grid;
  grid-column: auto / span 2;
  grid-row: auto / span 3;
}

示範未採用子格線時,格線項目內容可能無法與父項格線對齊。

套用子格線後,子格線內的格線項目會沿用父項格線設定的間距,並使用父項格線的欄和軌道流動格線項目。

.subgrid-container {
  display: grid;
  grid-column: auto / span 2;
  grid-row: auto / span 3;
  grid-template-columns: subgrid;
  grid-template-rows: subgrid;
}

示範如何套用子格線,使格線項目的內容與父項格線對齊。

在子格線中,您可以為任何格線項目套用相同的屬性和值。舉例來說,您可以擴充子格線內的格線項目,佔用兩個格線欄。

.featured-subgrid-item {
  grid-column: span 2;
}

示範如何讓子格項目跨越父格中的多個資料欄軌。

這也適用於格線列。

.subgrid-item {
  grid-row: span 2;
}

示範如何讓子格狀項目跨越父項格狀中的多個列軌。

以下是 CodePen 示範,在兩個維度中使用子格線:

對齊

格線版面配置使用的對齊屬性,與彈性方塊指南中介紹的相同。 在格線中,以 justify- 開頭的屬性一律會用於內嵌軸,也就是句子在書寫模式中的執行方向。

align- 開頭的屬性會用於區塊軸,也就是區塊在書寫模式中版面配置的方向。

分配額外空間

在本範例中,格線大於配置固定寬度軌道所需的空間。這表示格線的內嵌和區塊維度都有空間。 嘗試使用不同的 align-contentjustify-content 值,看看軌跡的行為。

請注意,使用 space-between 等值時,間距會變大,且任何跨越兩個軌道的格線項目也會變大,以吸收新增至間距的額外空間。

移動內容

由於 justify-selfalign-self 的初始值為 stretch,因此具有背景顏色的項目會填滿放置的格線區域。

在示範中變更 justify-itemsalign-items 的值,看看版面配置會如何變化。 格線區域不會變更大小,而是項目在定義的區域內移動。

隨堂測驗

測試你對格線的瞭解程度

下列何者是 CSS 格線用語?

這些水平和垂直分隔線會將格線劃分為多個部分。
社交圈
抱歉,CSS 格線沒有圓形的概念。
細胞
資料列和資料欄的單一交集會建立格線儲存格。
區域
多個儲存格。
訓練
抱歉,CSS 格線沒有列車的概念。
落差
儲存格之間的間距。
曲目
單一列或欄是格線中的軌道。
main {
  display: grid;
}

格線的預設版面配置方向為何?

資料列
如果未定義任何資料欄,格線子項會照常在區塊方向中配置。
如果存在 grid-auto-flow: column,則格線會以資料欄形式呈現。

auto-fitauto-fill 有何不同?

auto-fit 會將儲存格延展至符合容器大小,auto-fill 則不會。
auto-fill 會盡可能將項目放入範本,但不延展項目。Fit 讓他們加入。
auto-fit 會延展容器以配合子項,而 auto-fill 則會讓子項配合容器。
這些屬性的行為並非如此。

什麼是 min-content

與 0% 相同
0% 是父項方塊的相對值,而 min-content 則是方塊中文字和圖片的相對值。
最小的字母
雖然有最小的字母,但min-content並非指字母。
最長的字詞或圖片。
在「CSS is awesome」這個片語中,「awesome」就是min-content

什麼是 max-content

最長的句子或最大的圖片。
這是方塊內容要求或指定的最大大小。這是指最寬的句子或圖片。
最長的信。
雖然有最長的字母,但 max-content 指的並非字母。
最長的字。
最長的字是「min-content」。

什麼是自動刊登位置?

格線會根據瀏覽器啟發式方法,將子項項目依最佳順序排列。
瀏覽器不會變更內容順序,只有您自己的樣式會這麼做。
網格子項已獲得 grid-area 並放置在該儲存格中。
這是明確刊登位置,不是自動刊登位置。
在版面配置範本中,將未指派的格線項目放在下一個位置。
沒有明確區域的格線項目會放在下一個可用的格線儲存格

下列敘述是否正確:您只能在一個維度 (資料列或資料欄) 中建立子格線。

請再試一次。
您可以讓子格項目跨越多個列、多個欄,或同時跨越多個列和欄。

資源

本指南概略介紹了格線版面配置規格的各個部分。如要瞭解詳情,請參閱下列資源。