將來佈局之星Grid

grid是一個趨勢

Grid-layout不是爲了取代flex-layout,它是flex的補充。grid擅長二維佈局,flex擅長一維佈局。他們須要各司其職。css

千呼萬喚始出來的grid-layout終於在2017年3月開始支持獲得了部分瀏覽器的支持。
css3


flex並不能知足咱們對於頁面總體佈局的需求, Don't use flexbox for overall page layout這篇文章闡述了這麼一個觀點:不要用彈性盒子佈局總體的頁面。而咱們在日常使用中也能感覺到flex在作總體頁面佈局的時候,仍是有不完善的地方,仍是須要大量的inline-box、float來排布內容(// TODO 售後單詳情頁做爲例子);另一個問題咱們後面瞭解了grid以後會再說

grid = table2.0?

二維佈局方式,能夠按照行列方式排列內容。把頁面劃分爲幾塊,指定不一樣內容區塊的大小、位置和層級。算法

有觀點說grid很像table2.0,他們是有相同之處的。好比都是把元素排列成行和列。可是表格和grid的區別在於,表格是有內容結構的,不能很自由地在裏面作佈局。而grid內部元素能夠自由設定位置,容許重疊和設定層級的樣。segmentfault

幾個術語

網格容器 grid-container

網格容器爲其內容創建新的網格格式化上下文,是內部網格項的邊界。數組

網格線 grid-line

水平垂直分割線,構建出網格軌道、網格單元格和網格區域。就像經緯,分割出南北半球、東西半球,熱帶、南北溫帶、南北寒帶。網格線是有數字索引的,也能夠本身取名字。經緯線都是有數字的,也能夠命名,好比本初子午線、赤道。瀏覽器

網格軌道 grid-track

網格內容塊之間的水平或垂直的空間。濱盛、濱和、濱興、濱安、濱康,江陵、江暉、江漢、江虹。(郊區的經典命名,攤手)bash

網格單元格 grid-cell

網格內容的單位區塊,是能夠放置內容的最小區塊。好比用橫縱三條網格線劃分了頁面,那麼單元格就是九宮格中的一塊網絡

網格區域 grid-area

以網格線爲界劃定一塊區域。本來網易和阿里巴巴都是佔用一個單元格,如今都要擴建了,佔用兩個,兩個加起來就是它們各自的網格區域。框架

兩個例子

在瞭解具體的屬性以前,來一個最簡單的例子ide

這樣看會以爲grid仍是頗有趣的,先分塊,而後指定每一塊的區域範圍。塊是能夠重疊的。可是這只是開始,grid爲咱們帶來了17個新特性,在瞭解屬性以前再來看一個例子,經典佈局方案 —— 聖盃佈局 holy grail layout。

  • 網頁常見佈局:頁眉、頁腳、主要內容區塊、兩邊都有一個側邊列。
  • 兩邊帶有固定寬度,中間寬度可變
  • 中間三列內容等高
  • 頁腳總處於窗口的底部,即便內容沒有填滿整個窗口的高度
  • 響應式佈局,在較小的視窗中全部模塊都100%寬度顯示

你們能夠迅速在腦子裏碼一下這個界面寫個樣式,不至於說複雜 但總之不簡單吧。咱們看看grid是怎麼作的

// key code
.hg__header { grid-area: header;}
.hg__footer { grid-area: footer;}
.hg__main { grid-area: main;}
.hg__left { grid-area: navigation;}
.hg__right { grid-area: ads;}

.hg {
    display: grid;
    grid-template-areas:    "header header header"
                            "navigation main ads"
                            "footer footer footer";
    grid-template-columns: 250px 1fr 300px;
    grid-template-rows: 100px 
                        1fr
                        80px;
    min-height: 100vh;
}複製代碼

步驟:

  1. 定義網格

    1. 設定網格區域別名,grid-area: ,指定塊所在區域的時候方便引用。前一個簡單的例子,grid-area是用來指定網格區域上下左右的網格線各是什麼,因此grid-area既能夠指定網格區域的大小和位置,還能夠設定區域的別名。
      grid-area: main;
           grid-row-start: main;
           grid-column-start: main;
           grid-row-end: main;
           grid-column-end: main;複製代碼
    2. grid-template-areas: "- - -" "- - -" "- - -";能夠很是直觀指定網格的佈局。它的值是空格分隔的字符串數組,每個字符串表明一行。每個字符串中是空格分隔的網格單元格列表,一個網格區域要跨幾列就寫幾回。好比例子中header、footer寫了三次,它們都是跨整個區域寬度的。
  2. 設定單元格的高度和寬度

    有一個css3的新單位,fr,在一串數值中出現的話表示根據比例分配某個方向上的剩餘空間。設定行高的時候分行寫是爲了清晰一點。

  3. 設定固定位置的頁腳

  4. 響應式佈局,使用媒體查詢。重置佈局和行高

grid-container

1. grid-template-columns | grid-template-rows

grid-template-columns: <track list>定義網格的行數、列數、網格大小

有不少中形式,常見的是這麼幾種:

grid-template-columns: 100px 1fr;
grid-template-columns: [linename] 100px;    // 定義網格線名字
grid-template-columns: [linename1] 100px [linename2 linename3]; // 一條網格線多個名字
grid-template-columns: minmax(100px, 1fr);  // 最小100px, 最大滿屏
grid-template-columns: fit-content(40%);    // 指定最大值不超過屏寬40%
grid-template-columns: repeat(3, 200px);    // 三列200px複製代碼
// 給網格線指定名字
.box {
    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];
}複製代碼

2. grid-template-areas

定義網格區域,使用grid-area調用聲明好的網格區域名稱放置對應的網格項目。定義一個顯式的網格區域。

3. grid-row-gap、grid-column-gap

定義網格之間的間距(不包括grid-item到容器邊緣的間距)

4. justify-items: start | end | center | stretch(默認);

定義網格子項的內容水平方向上的對齊方式,相似於flex-container的justify-content,只不過沒有space-around和space-between

1bc096d4ee73927e.png
1bc096d4ee73927e.png

35fecd4fbf754a84.png
35fecd4fbf754a84.png

9a2b4b82c9b6a65b.png
9a2b4b82c9b6a65b.png

85e7fb64351898e4.png
85e7fb64351898e4.png

5. align-items: start | end | center | stretch(默認);

定義網格子項的內容垂直方向上的對齊方式,相似於flex-container的align-items

7a410b6d17acd72e.png
7a410b6d17acd72e.png

20f8f733235797ea.png
20f8f733235797ea.png

9e1f32b77d573d04.png
9e1f32b77d573d04.png
85e7fb64351898e4.png
85e7fb64351898e4.png

6. justify-content: start | end | center | stretch | space-around | space-between | space-evenly;

當出現網格容器容量大於網格總大小,好比每個網格子項都用了固定值的時候,指定網格在網格容器中和縱軸的對齊方式。後面三個屬性值的區別在:

  1. space-around: 始末兩端的間距是網格間距的一半
  2. space-between: 始末兩端的間距爲零
  3. space-evenly: 始末兩端的間距與網格間距相等




7. align-content: start | end | center | stretch | space-around | space-between | space-evenly;

和justify-content對齊方向垂直,指定網格和橫軸的對齊方式。

e14e12bdfbf2e3e4.png
e14e12bdfbf2e3e4.png

8006fb09977ce5c8.png
8006fb09977ce5c8.png

61ffebd9e0da3f0b.png
61ffebd9e0da3f0b.png
28e49f66a9c4455a.png
28e49f66a9c4455a.png

b9bfc04642c818d7.png
b9bfc04642c818d7.png

f1845a4b578d8191.png
f1845a4b578d8191.png

f06633de75642a36.png
f06633de75642a36.png

8. grid-auto-columns、grid-auto-rows; grid-auto-flow

grid-auto-columns | grid-auto-rows做用是網格單元格不夠的時候建立隱式的網格放置grid-item。看一個例子

咱們只定義了一個1×1的網格容器,box1放了進來,而後其餘的三個怎麼辦呢?漏出來。box2接在box1後面渲染至屏幕右側,box3和box4在底下渲染,高度僅僅爲內容高度。

指定了grid-auto-columns: 200px; grid-auto-rows: 200px;,至關於在容器中橫縱都建立了更多的隱式的200*200的網格單元來盛放可能多出來的元素。

與之相關的還有另外一個屬性:grid-auto-flow,在咱們沒有設定這個屬性的時候,多餘的元素也按照從左到右從上到下的順序排列,這個屬性是控制自動佈局算法的。

grid-auto-flow: row | column | row dense | column dense;

  1. row爲默認值,表明自動佈局算法在每一行中依次填充,只有必要時纔會添加新行。
  2. column表明自動佈局算法在每一列中依次填充,只有必要時纔會添加新行。
  3. dense表明告訴自動佈局算法若是更小的子項出現時嘗試在網格中填補漏洞。(不建議使用,可能會使佈局產生混亂)

grid-item

1. grid-column-start | grid-column-end | grid-row-start | grid-row-end

grid-row: grid-row-start / grid-row-end
grid-column: grid-column-start / grid-column-end | grid-column-start | span <value>複製代碼

f0988aebf7ce8786.png
f0988aebf7ce8786.png

若是沒有顯式設置grid-column-end/grid-row-end,網格子項將默認跨越一個網格單元。此外,網格子項能夠互相重疊,可使用z-index來控制他們的層疊順序。

有一些元素,咱們想讓它貫穿整個視口,好比像 header、footer,對於小屏幕,兩列布局:

.header, .footer {
  grid-column: 1 / 3;
}複製代碼

不幸的是,當咱們換到大屏的時候,一行12列,這些元素將僅僅佔滿前兩列,並不會佔滿12列,咱們須要定義新的grid-column-end,而且把他的值設爲 13. 這種方式比較麻煩,還有一種簡單的方式,grid-column: 1 / -1;,這樣不論在什麼屏幕尺寸下,它們都是佔滿整行的了。就像下面這樣:

.header, .footer {
  grid-column: 1 / -1;
}複製代碼

2. grid-area

grid-area: <name> | grid-row-start / grid-column-start / grid-row-end / grid-column-end

3. justify-self: start | end | center | stretch 網格單元格內容水平方向上的對齊方式 。與flex中的justify-self。

c096a95f6300d932.png
c096a95f6300d932.png

bb01f2f4ea312d78.png
bb01f2f4ea312d78.png

3ca2ef564834e834.png
3ca2ef564834e834.png

caddebe3320088bf.png
caddebe3320088bf.png

4. align-self: start | end | center | stretch 網格單元格內容垂直方向上的對齊方式 。相似與flex中的align-self。

1f1b1806e925fe2b.png
1f1b1806e925fe2b.png

grid-align-self-end.png
grid-align-self-end.png

0ad87bbf53ecc6a3.png
0ad87bbf53ecc6a3.png

caddebe3320088bf.png
caddebe3320088bf.png

grid-layout帶來的函數

1. repeat()

repeat()提供了一個緊湊的聲明方式。若是行列太多而且是規則的分佈,咱們能夠用函數來作網格線的排布。

grid-template-columns: repeat(3, 20px [col-start]) 5%;
// 等價於
grid-template-columns: 20px [col-start] 20px [col-start] 20px [col-start] 5%;
}複製代碼

2. minmax()

minmax()至關於爲網格線間隔指定一個最小到最大的區間。若是min>max,這個區間就失效了,展現的是min。

3. fit-content()

fit-content()至關於 min('max-content', max('auto', argument));

flex佈局的另外一個問題

flex-layout的佈局另一個問題是,在有大量內容繪製到頁面上、或者內容更改的狀況下,在2g或者網絡加載不穩定的時候,頁面是不穩定的。Flexbox vs Grid page layout。內容以流式從服務端獲取用戶能夠在頁面所有加載出來以前就看到內容,可是在flex佈局下會致使佈局的重排。正是由於flex自己就是一個彈性的佈局。但grid也不是徹底能夠避免佈局重排的問題——有前提:

必須讓你的網格劃分是能夠預先肯定的,好比是根據視窗寬高肯定的。若是是根據內容而定,那麼也是會崩壞的。複製代碼

下面的例子中,網格的列寬根據內容而定,所以也會根據內容而變。後面的aside並無定義在網格容器當中,是一個動態建立的元素。一旦被建立就會致使頁面重繪

.container {
    display: grid;
    grid-template-columns:
    (foo)   max-content,
    (bar)   min-content,
    (hello) auto;
}

aside {
    grid-column: 4;
}複製代碼

可是也不要放棄flex-layout,它是目前爲止最厲害的頁面佈局屬性,是時代召喚的結果,只是它並不適合佈局整個頁面框架。flex在響應式佈局中是很關鍵的,它是內容驅動型的佈局。不須要預先知道會有什麼內容,能夠設定元素如何分配剩餘的空間以及在空間不足的時候如何表現。顯得較爲強大的是一維佈局的能力,而grid優點在於二維佈局。這也是他們設計的初衷。

大概能夠設想,網格佈局被普遍支持以後會出現不少網格佈局內嵌flex的佈局情形。

subgrid暫時尚未瀏覽器支持,規範也是在改動之中的,因此先不介紹了。

參考

Don't use flexbox for overall page layout

(譯)原生CSS網格佈局學習筆記

網格佈局(CSS Grid Layout)淺談

CSS Grid Layout

擁抱將來的CSS佈局方式:flex與grid佈局

A Complete Guide to CSS Grid Layout

相關文章
相關標籤/搜索