[譯] 簡單的響應式現代 CSS 網格佈局

MeFelixWang發表於2018-09-02

在本文中,我們將展示如何建立響應式現代 CSS 網格佈局,演示如何在舊瀏覽器上使用降級程式碼,如何逐步新增 CSS 網格,如何使用對齊屬性重新構建小型裝置的佈局以及居中元素。

在之前的文章中,我們探索了四種不同的技術,可以輕鬆構建響應式網格佈局。那篇文章是在 2014 年寫的 —— 在 CSS 網格可用之前 —— 因此在本教程中,我們將使用類似的 HTML 結構,但使用現代 CSS 網格佈局。

在本教程中,我們將使用浮動來建立一個帶有基本佈局的演示專案,然後使用 CSS 網格對其進行增強。我們將演示許多有用的實用工具,例如居中元素,跨越元素,以及通過重新定義網格區域和使用媒體查詢輕鬆更改小型裝置上的佈局。你可以在此 pen 中找到程式碼:codepen.io/SitePoint/p…

響應式現代 CSS 網格佈局

在我們開始建立響應式網格演示專案之前,首先介紹一下 CSS 網格。

CSS 網格是一個功能強大的二維繫統,在 2017 年被新增到大多數現代瀏覽器中。它極大地改變了我們建立 HTML 佈局的方式。網格佈局允許我們在 CSS 而不是 HTML 中建立網格結構。

除了 IE11 之外,大多數現代瀏覽器都支援 CSS 網格,IE11 支援可能產生一些問題的舊版標準。你可以使用 caniuse.com 來檢查支援情況。

網格佈局有一個 display 屬性為 gridinline-grid 的父容器。容器的子元素是網格項,由強大的網格演算法隱式定位。你還可以應用不同的類來控制網格項的放置,尺寸,位置和其他方面的東西。

讓我們從一個基本的 HTML 頁面開始。建立 HTML 檔案並新增以下內容:

<header>
    <h2>CSS Grid Layout Example</h2>
</header>
<aside>
  .sidebar
</aside>

<main>
  <article>
    <span>1</span>
  </article>
  <article>
    <span>2</span>
  </article>
  <!--... -->
  <article>
    <span>11</span>
  </article>
</main>

<footer>
  Copyright 2018
</footer>
複製程式碼

我們使用 HTML 語義標籤來定義頁面的頭部,側邊欄,主體和頁尾部分。在主體部分中,我們使用 <article> 標籤新增一組子項。<article> 是一個 HTML5 語義標籤,可用於包裝獨立和自包含的內容。單個頁面可以包含任意數量的 <article> 標籤。

這是此階段頁面的螢幕截圖:

The basic HTML layout so far

接下來,讓我們新增基本的 CSS 樣式。在文件的頭部新增 <style> 標籤並新增以下樣式:

body {
  background: #12458c;
  margin: 0rem;
  padding: 0px;
  font-family: -apple-system, BlinkMacSystemFont,
            "Segoe UI", "Roboto", "Oxygen", "Ubuntu", "Cantarell",
            "Fira Sans", "Droid Sans", "Helvetica Neue",
            sans-serif;
}

header {
  text-transform: uppercase;
  padding-top: 1px;
  padding-bottom: 1px;
  color: #fff;
  border-style: solid;
  border-width: 2px;
}

aside {
  color: #fff;
  border-width:2px;
  border-style: solid;
  float: left;
  width: 6.3rem;
}

footer {
  color: #fff;
  border-width:2px;
  border-style: solid;
  clear: both;
}

main {
  float: right;
  width: calc(100% - 7.2rem);
  padding: 5px;
  background: hsl(240, 100%, 50%);
}

main > article {
  background: hsl(240, 100%, 50%);
  background-image: url('https://source.unsplash.com/daily');
  color: hsl(240, 0%, 100%);
  border-width: 5px;
}
複製程式碼

這是一個小型演示頁面,因此我們將直接設定標籤樣式以提高可讀性,而不是應用類命名系統。

我們使用浮動將側邊欄定位到左側,將主體部分定位到右側,將側邊欄的寬度設定為固定的 6.3rem。然後我們使用 CSS calc() 函式來計算並設定主體部分可用的剩餘寬度。主體部分包含一些垂直排列的子項。

A gallery of items organized as vertical blocks

佈局並不完美。例如,側邊欄與主體內容部分的高度並不相同。有各種 CSS 技術可以解決這些問題,但大多數都是 hack 或變通方法。由於此佈局是網格的降級,因此快速減少的使用者也可以看到效果。降級是可用的,足夠了。

最新版本的 Chrome、Firefox、Edge、Opera 和 Safari 都支援 CSS 網格,這意味著如果你的訪問者使用這些瀏覽器,則無需提供降級。你還需要考慮常青瀏覽器。最新版本的 Chrome、Firefox、Edge 和 Safari 是常青瀏覽器。也就是說,它們會在不提示使用者的情況下自動靜默更新。為確保你的佈局適用於每個瀏覽器,你可以從預設的基於浮動的降級開始,然後使用漸進增強技術應用現代網格佈局。那些使用舊瀏覽器的使用者將無法獲得相同的體驗,但這樣足夠了。

漸進增強:你不必全部覆蓋

在降級佈局的頂部新增 CSS 網格佈局時,實際上不需要覆蓋所有標籤或使用完全獨立的 CSS 樣式:

  • 在不支援 CSS 網格的瀏覽器中,你新增的網格屬性將被忽略。
  • 如果你使用浮動來佈置元素,請記住網格項優先於浮動項。也就是說,如果將 float: left|right 樣式新增到也是網格元素的元素(具有 display: grid 樣式的父元素的子元素)中,則將忽略浮動以支援網格。
  • 可以使用 @supports 規則在 CSS 中檢查特定功能的支援情況。這允許我們在必要時覆蓋降級樣式,而舊瀏覽器會忽略 @supports 程式碼塊。

現在,讓我們在頁面中新增 CSS 網格。首先,我們讓 <body> 成為一個網格容器並設定網格列,行和區域:

body {
  /*...*/
  display: grid;
  grid-gap: 0.1vw;
  grid-template-columns: 6.5rem 1fr;
  grid-template-rows: 6rem 1fr 3rem;
  grid-template-areas: "header   header"
                       "sidebar content"
                       "footer footer";  
}
複製程式碼

我們使用 display:grid 屬性將 <body> 標記為網格容器。將網格 gap 設為 0.1vw。gap 允許你在網格單元格之間建立間距,而不是使用外邊距。

我們用 grid-template-columns 來新增兩列。第一列寬度固定為 6.5rem,第二列為剩餘寬度。fr 是一個小數單位,1fr 等於可用空間的一部分。

接下來,我們用 grid-template-rows 新增三行。第一行高度固定為 6rem,第三行高度固定為 3rem,剩餘可用空間(1fr)指定給第二行。

然後我們用 grid-template-areas 將由列和行的交集產生的虛擬單元格分配給區域。現在我們需要使用 grid-area 實際定義區域模板中指定的區域:

header {
  grid-area: header;
  /*...*/
}
aside {
  grid-area: sidebar;
  /*...*/
}
footer {
  grid-area: footer;
  /*...*/
}
main {
  grid-area: content;
  /*...*/
}
複製程式碼

我們的大多數降級程式碼對 CSS 網格沒有任何副作用,除了主體部分的寬度 width: calc(100% - 7.2rem);,它在減去側邊欄的寬度加上外邊距/內邊距後計算主體部分的剩餘寬度。

這是結果的螢幕截圖。注意主體區域並沒有佔滿剩餘的全部寬度:

Progressive layout with current grid settings

要解決此問題,我們可以在支援網格時新增 width: auto;

@supports (display: grid) {
  main {
    width: auto;
  }
}
複製程式碼

這是結果的螢幕截圖:

The effect of adding width: auto

新增巢狀網格

網格子項可以是網格容器本身。讓我們將主體部分作為一個網格容器:

main {
  /*...*/
  display: grid;  
  grid-gap: 0.1vw;
  grid-template-columns: repeat(auto-fill, minmax(12rem, 1fr));
  grid-template-rows: repeat(auto-fill, minmax(12rem, 1fr));
}
複製程式碼

我們將網格 gap 設為 0.1vw 並使用 repeat(auto-fill, minmax(12rem, 1fr)); 函式定義列和行。auto-fill 選項會嘗試使用盡可能多的列或行填充可用空間,必要時會建立隱式列或行。如果要將可用列或行放入可用空間,則需要使用 auto-fit。詳情請閱讀 auto-fillauto-fit 的差異

這是結果的螢幕截圖:

A nested grid

使用網格 grid-columngrid-rowspan 關鍵詞

CSS 網格提供了 grid-columngrid-row,它們允許你使用網格線在父網格中對網格項進行定位。它們是以下屬性的簡寫:

  • grid-row-start: 指定網格行中網格項的起始位置
  • grid-row-end: 指定網格行中網格項的結束位置
  • grid-column-start: 指定網格列中網格項的起始位置
  • grid-column-end: 指定網格列中網格項的結束位置。

你還可以使用關鍵字 span 指定要跨越的列數或行數。

我們讓主體區域的第二個子項跨越四列、兩行,並讓其從第二列和第一行(也是它的預設位置)開始放置:

main article:nth-child(2) {
  grid-column: 2/span 4;
  grid-row: 1/span 2;
}
複製程式碼

這是結果的螢幕截圖:

Second child spanning four columns and two rows

使用網格對齊工具

我們想讓頭部,側邊欄和頁尾中的文字以及 <article> 元素內的數字居中。

CSS 網格提供了六個屬性 justify-itemsalign-itemsjustify-contentalign-contentjustify-selfalign-self,可用於對齊和分散網格項。它們實際上是 CSS 盒對齊模型的一部分。

在頭部內,側邊欄,文章和頁尾選擇器內新增以下內容:

display: grid;
align-items: center;
justify-items: center;
複製程式碼
  • justify-items 用於沿行軸或在水平方向上對齊網格項。
  • align-items 沿著列軸或在垂直方向上對齊網格項。它們都可以使用 startendcenterstretch

這是居中元素後的螢幕截圖:

Numbers are now centered horizontally and vertically in each cell

重構小型裝置中的網格佈局

我們的演示佈局適用於中型和大型螢幕,但可能不是在小螢幕裝置中構建頁面的最佳方式。使用 CSS 網格,我們可以輕鬆地更改此佈局結構,使其在小型裝置中平滑過渡 —— 通過重新定義網格區域及使用媒體查詢。

這是在新增程式碼重構小型裝置上的佈局之前的螢幕截圖:

The initial mobile layout

現在,新增以下 CSS 程式碼:

@media all and (max-width: 575px) {
  body {
    grid-template-rows: 6rem  1fr 5.5rem  5.5rem;  
    grid-template-columns: 1fr;
    grid-template-areas:
      "header"
      "content"
      "sidebar"
      "footer";
    }
}
複製程式碼

在寬度 <= 575px 的裝置上我們使用寬度分別為 6rem1fr5.5rem5.5rem 的四行,以及佔滿所有可用空間的一列。我們還重新定義了網格區域,讓側邊欄在小型裝置上處於主體內容區域下面的第三行:

The developing mobile layout

請注意,側邊欄的寬度並未佔滿可用寬度。這是由降級程式碼引起的,所以我們需要做的是在支援網格的瀏覽器上用 width: auto; 覆蓋掉 width: 6.3rem;

@supports (display: grid) {
  main, aside {
    width: auto;
  }
}
複製程式碼

這是最終結果的螢幕截圖:

The final mobile layout

你可以在本文開頭附近的 pen 中找到最終程式碼,也可以直接訪問此 pen

結論

在本教程中,我們使用 CSS 網格建立了一個響應式演示佈局。我們已經演示瞭如何針對舊版瀏覽器使用降級程式碼,逐步新增 CSS 網格,在小型裝置中重構佈局以及使用對齊屬性居中元素。

如果發現譯文存在錯誤或其他需要改進的地方,歡迎到 掘金翻譯計劃 對譯文進行修改並 PR,也可獲得相應獎勵積分。文章開頭的 本文永久連結 即為本文在 GitHub 上的 MarkDown 連結。


掘金翻譯計劃 是一個翻譯優質網際網路技術文章的社群,文章來源為 掘金 上的英文分享文章。內容覆蓋 AndroidiOS前端後端區塊鏈產品設計人工智慧等領域,想要檢視更多優質譯文請持續關注 掘金翻譯計劃官方微博知乎專欄

相關文章