天天看點

CSS Grid 新手入門

基本概念

MDN上的解釋是這樣的

CSS Grid Layout excels at dividing a page into major regions or defining the relationship in terms of size, position, and layer, between parts of a control built from HTML primitives.

另外,下面一段話摘自A Complete Guide to Grid,對于CSS Grid會有更加清楚地釋義

CSS Grid Layout (aka “Grid”), is a two-dimensional grid-based layout system that aims to do nothing less than completely change the way we design grid-based user interfaces.

總結來說:

  • CSS Grid 是一個二維的布局系統
  • CSS Grid 相比傳統布局在頁面整體劃分布局上更加出色
  • CSS Grid 并不是隻能單獨使用,依然可以搭配

    Flexbox

    以及傳統定位布局一起使用

相容性

摘自Can I Use中對

CSS Grid

的相容性分析。

CSS Grid 新手入門

從圖中可以看出浏覽器的相容率整體達到84.16%,并且都是無需帶字首的。

基本概念

網格是一組相交的水準線和垂直線,它定義了網格的列和行。我們可以将網格元素放置在與這些行和列相關的位置上。

Grid Container (網格容器)

在一個元素上應用了

display: grid;

或者

display: inline-grid;

那麼就建立了一個網格容器,它下面的直接子元素都會成為網格元素,例如:

<style>
.wrapper {
  display: grid;
}
</style>

<div class="wrapper">
  <div class="custom">One</div>
  <div class="custom">Two
    <p>I have some more content in.</p>
    <p>This makes me taller than 100 pixels.</p>    
  </div>
  <div class="custom">Three</div>
  <div class="custom">Four</div>
  <div class="custom">Five</div>
</div>           

複制

CSS Grid 新手入門

從網頁的基本表現看,和平常的布局沒有什麼差别,Mac OSX 【alt + command + I】,Windows 【F11】打開網頁檢查器即可看出網格布局。

CSS Grid 新手入門

Grid Tracks (網格軌迹)

從字面上的意譯來看還是比較繞口,但是我換一種說法你可能就會明白了。可以把

tracks

看做是table中的行和列就好了。

CSS Grid 新手入門

定義一個網格中的行和列的數量分别使用

grid-template-rows

grid-template-columns

來确定這個表格會有多少行以及多少列。例如:

.container {
  display: grid;
  grid-template-rows: 100px 50px 100px;
  grid-template-columns: 100px 100px 100px;
}           

複制

上面的代碼寫出了一個

3 x 3

的網格

CSS Grid 新手入門

在圖中可以看出網格的數量,其中的子元素會根據這些網格的數量自動填充。如果事先不知道要劃分多少行,可以使用隻使用

grid-template-columns

來确定多少列,行數會根據有多少子item來自動計算,例如下面的:

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

複制

CSS Grid 新手入門

5個元素如果是劃分3列,那麼就應該會有兩行。

fr

如果想要均分容器的寬度,那麼可以使用新引入的機關

fr

,新的

fr機關

代表網格容器中可用空間的一等份。例如:

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

複制

repeat()

可以使用

repeat()

函數來标記軌道重複使用的部分,例如上面的樣式就可以寫成:

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

複制

每行高度

如果想确定使用每行高度,可以使用

grid-auto-rows: 100px;

來确定每行隻有100px

minmax()

如果想讓每行的高度随着内容自動填充,那麼可以使用

minmax()

來确定最小值與最大值,例如:

.container {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-auto-rows: minmax(100px, auto);
}           

複制

上面的樣式規定了一個3列布局,每行的高度最少為100px的網格。

CSS Grid 新手入門

Grid Line (網格線)

網格線用來建構整個網格,包括水準的和豎直的

CSS Grid 新手入門

當一個網格被建構出來,網格線就會被預設地有一個辨別,看下圖:

CSS Grid 新手入門
辨別的線可以是正向也可以是逆向的,例如第一行的線的辨別就是[1 -4],那麼線辨別有什麼用?線辨別主要用來确定一個子元素要占有的面積,也成為Grid Area,例如下面的代碼:
.one {
  grid-column-start: 1;
  grid-column-end: 4;
  grid-row-start: 1;
  grid-row-end: 3;
}           

複制

CSS Grid 新手入門

給線命名

預設的線的辨別都是用數字來表示的,當然也可以給線來命名,具體如下:

.container {
  grid-template-columns: [first] 40px [line2] 50px [line3] auto [col4-start] 50px [five] 40px [end];
  grid-template-rows: [row1-start] 25% [row1-end] 100px [third-line] auto [last-line];
}           

複制

CSS Grid 新手入門

從圖中可以看出,第一列的第一根線被命名成了

first

,那麼我們就可以将之前的寫法稍微改一下了:

.one {
  grid-column-start: first;
  grid-column-end: col4-start;
  grid-row-start: 1;
  grid-row-end: 3;
}           

複制

關于更多的線的命名使用方法,可以參看Naming lines when defining a grid,這裡隻是簡單的介紹

Grid Cell (網格單元)

可以簡單了解為一個

table

中的一個單元格

CSS Grid 新手入門

Grid Area (網格面積)

可以通過規定一個

item

的起始行和起始列來規定一個area,注意:area必須為一個 規則的舉行,而不能為一個類似于

L

形狀的圖形

CSS Grid 新手入門

通過行和列辨別來确定一個面積,例如:

.container {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-auto-rows: minmax(100px, auto);
}
.one {
  grid-column-start: 1;
  grid-column-end: 3;
  grid-row-start: 1;
  grid-row-end: 3;
}           

複制

上面的代碼就劃定了一個兩行兩列的區域,上面的寫法可以簡寫為:

.one {
  grid-column: 1 / 3;
  grid-row: 1 / 3;
  
  /* 這種寫法對應: */
  grid-column: [grid-column-start] / [grid-column-end];
  grid-row: [grid-row-start] / [grid-row-end];
}           

複制

或者使用

grid-area

.one { 
  grid-area: 1 / 1 / 3 / 3;
  
  /* 這種寫法分别對應: */
  grid-area: [grid-row-start] / [grid-column-start] / [grid-row-end] / [grid-column-end];
}           

複制

還可以配合

grid-template-areas

來提前劃分區域,例如:

.container {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-auto-rows: minmax(100px, auto);
  grid-template-areas: 
   "header header header"
   "siderbar main main"
   "footer footer footer"
}           

複制

上面的樣式中,規定了一個

3 x 3

的網格,并且劃分了區域,第一行為

header

,第二行為左側為

siderbar

,右側為

main

,第三行為

footer

,那麼剩餘的工作就是制定子元素對應的區域即可,例如:

.header {
  grid-area: header;
}
.siderbar {
  grid-area: siderbar;    
}
.main {
  grid-area: main;    
}
.footer {
  grid-area: footer;
}           

複制

對應的網頁檔案為:

<div class="container">
  <div class="custom header">header</div>
  <div class="custom siderbar">siderbar</div>
  <div class="custom main">main</div>
  <div class="custom footer">footer</div>
</div>           

複制

最終的效果為:

CSS Grid 新手入門

Grid Gutters (網格間距)

分為行間距和列間距,類似于

table

中的

colspan

rowspan

,具體例子如下:

.grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-auto-rows: minmax(100px, auto);
  grid-gap: 10px;
  
  /* 這裡的grid-gap相當于: */
  grid-column-gap: 10px;
  grid-row-gap: 10px;
}           

複制

從上一個例子中,我也設定了

10px

的間距,可以從圖中看出來。

Grid z-index

類似于

position: absolute;

絕對定位之後的層級,後面渲染的item會覆寫前面的,是以下例中的item為

Two

的會覆寫在

One

.z-index-1 {
  grid-column: 1 / 3;
  grid-row: 1;
  background-color: aliceblue;
}
.z-index-2 {
  grid-column: 2 / 4;
  grid-row: 1 / 3;
  background-color: antiquewhite;
}           

複制

CSS Grid 新手入門

調整item1的index之後

z-index: 2;

,會看到item1會覆寫在item2上面

<div class="custom z-index-1" style="z-index: 2;">One</div>
<div class="custom z-index-2" style="z-index: 1;">Two</div>           

複制

CSS Grid 新手入門

網格布局中的對齊

如果熟悉

flex

,那麼一定會知道flex中的布局,相同的,在

grid

布局中也有相應的布局

網格布局的兩條軸線

When working with grid layout you have two axes available to align things against –

the block axis

and

the inline axis

. The block axis is the axis upon which blocks are laid out in block layout. If you have two paragraphs on your page they display one below the other, so it is this direction we describe as the block axis.
  • 塊方向的列軸
CSS Grid 新手入門
  • 文字方向的行軸
CSS Grid 新手入門

以上的文字以及圖檔均摘自MDN

對齊列項目

對齊列項目主要的CSS聲明有兩個:

align-items

以及

align-self

align-items

用于所有item的設定,

align-self

可以單獨進行自定義。這兩個聲明可取的屬性值有以下幾種:

  • auto
  • normal
  • start
  • end
  • center
  • stretch
  • baseline
  • first baseline
  • last baseline

下面我們用一個栗子分别說明如下(栗子摘自MDN):

<style>
.wrapper {
  display: grid;
  grid-template-columns: repeat(8, 1fr);
  grid-gap: 10px;
  grid-auto-rows: 100px;
  grid-template-areas: 
    "a a a a b b b b"
    "a a a a b b b b"
    "c c c c d d d d"
    "c c c c d d d d";
}
.item1 {
  grid-area: a;
  background-color: aqua;
}
.item2 {
  grid-area: b;
  background-color: aqua;
}
.item3 {
  grid-area: c;
  background-color: aqua;
}
.item4 {
  grid-area: d;
  background-color: aqua;
}
</style>

<div class="wrapper">
  <div class="custom item1">Item 1</div>
  <div class="custom item2">Item 2</div>
  <div class="custom item3">Item 3</div>
  <div class="custom item4">Item 4</div>
</div>           

複制

定義了一個

8 x 4

列的網格,其中劃分為均勻的四個區域,分别用

item[1,2,3,4]

來進行填充,預設的對齊方式為

stretch

CSS Grid 新手入門

可以通過幾個

select

來控制對齊方式,分别通過控制整體和單個item的對齊

CSS Grid 新手入門

相對于容器的列對齊

使用

align-content

這個屬性聲明來決定整個網格在容器中的列方向的布局,可選的值如下:

  • normal
  • start
  • end
  • center
  • stretch
  • space-around
  • space-between
  • space-evenly
  • baseline
  • first baseline
  • last baseline
CSS Grid 新手入門

可以看到圖中,當選擇了

align-content: end

的時候,整個網格就會在容器的下方對齊。

更多内容請參看MDN CSS_Grid_Layout

Grid 布局和其他布局的關系

Grid 和 Flex

The basic difference between CSS Grid Layout and CSS Flexbox Layout is that flexbox was designed for layout in one dimension - either a row or a column. Grid was designed for two-dimensional layout - rows, and columns at the same time.

Grid布局和Flex布局最大的不同點就是:Grid布局是二維布局,針對行和列的布局,而Flex布局為一維布局,隻針對行和列的當行布局。

Tips: 這兩種布局并不沖突,可以搭配使用。可以在整體布局上采用

grid

布局,而細節處理可以使用

flex

下面看一個栗子,來看看這兩種布局之間有什麼不同(栗子來源MDN):

編寫一個自動換行适應的布局

  • Flex方式
<style>
  .flex-wrapper {
    display: flex;
    flex-wrap: wrap;
  }
  .flex-wrapper > div {
    flex: 1 1 200px;
  }
</style>

<div class="flex-wrapper">
  <div>One</div> 
  <div>Two</div>
  <div>Three</div>
  <div>Four</div>
  <div>Five</div>
</div>           

複制

  • Grid 方式
<style>
  .grid-wrapper {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
  }
</style>           

複制

使用

flex-wrap: wrap;

來限定如果一行不足就自動換行。使用

auto-fill

來根據容器寬度決定會有多少列,并且使用

minmax()

函數來确定最小為200px,最大為容器寬度來自适應。

如果螢幕上有很多剩餘的空間,

flex

布局會均分成5列,而

grid

布局則會始終為3列,并且餘下的兩個item也長度也 相同,而如果螢幕寬度調整為小于200時,

flex

布局會彈性地變為1列,但是

grid

布局如果沒有使用

auto-fill

時,會始終為設定的列數。

另外,

grid

布局和

flex

布局還有一點不同的是,在最開始的配置設定的時候

grid

布局會優先劃分布局,即會優先規定出螢幕中可以最大容忍出 多少個符合條件(這裡是最小為200px, 最大為1fr)的item數量,然後依次填充。

CSS Grid 新手入門

Grid 和 絕對定位

.positioned {
  grid-template-columns: repeat(4,1fr);
  grid-auto-rows: 200px;
  grid-gap: 20px;
  position: relative;
}
.box3 {
  grid-column-start: 2;
  grid-column-end: 4;
  grid-row-start: 1;
  grid-row-end: 3;
  position: absolute;
  top: 40px;
  left: 40px;
}           

複制

CSS Grid 新手入門

如果父容器有定位辨別

relative

Or

absolute

等,那麼下面的子item會根據原始它們應該布局的位置定位,反之如果父容器沒有 定位辨別,那麼應用了

position: absolute;

會脫離

gird

布局,并且按照CSS傳統的方式布局。

備注:

  • 文中部分圖檔以及案例均來自于A Complete Guide to Grid和MDN
  • 本文代碼倉庫:https://github.com/Rynxiao/css-grid-tutorial/
  • 本文部分執行個體:http://rynxiao.com/css-grid-tutorial/

參考連接配接

  • MDN Css Grid Layout
  • A Complete Guid to Grid