本文爲譯文,由於筆者也是最近開始嘗試翻譯文章,若有翻譯地不合理或者不正確的地方,歡迎指出。原文地址:CSS Grid: illustrated introduction。css
我還記得第一次學習CSS知識的時候,我是如何興奮地學習使用float和inline展現元素在想要的佈局位置。我想知道若是當時有一個二維佈局系統,我會做何反應。事實上,即便到如今我仍是感到興奮,由於咱們編寫CSS的方式以及咱們編寫標記語言的方式改變了一切。使用CSS網格,使得咱們構建響應式的、動態的、源碼順序獨立的佈局比以前更加容易。html
注意,源碼順序獨立只是根據字面翻譯,我理解的含義是編寫的html標籤的順序跟頁面上展現標籤的順序無關,咱們能夠經過CSS 網格樣式任意修改元素在頁面上的展現順序。算法
在本文中,咱們將學習使用全部的CSS網格知識來構建簡單的和一些不太容易的佈局。咱們將定義一切CSS網格知識,而後接着將挖掘得更深一點,看看咱們可使用CSS網格實現什麼樣的佈局。話雖如此,若是你已經準備好學習一種新的佈局方式,吃下紅色藥丸,我會告訴你兔子洞到底有多深。編程
在咱們開始學習以前,我想提出一些或許你也可能有的一些顧慮,同時確保咱們熟悉CSS網格的基礎知識和術語。瀏覽器
Q:CSS網格會替代flex-box佈局嗎?框架
A:固然,CSS網格不會替代flex-box,這兩種佈局是針對不一樣的使用場景。事實上,它們還能夠很好地搭配使用。咱們能夠在CSS網格佈局中使用flex佈局,反之亦然。函數
Q:CSS網格佈局和flex-box佈局有什麼不一樣?佈局
A:它們有不少不一樣點,最主要的區別就是flex-box是一種一維的佈局系統,而CSS網格是一種二維的佈局系統。讓咱們看看下圖:學習
Q:爲何不使用Bootstrap呢?flex
A:我認爲最好的回答是引用Jen Simmons的表述:
使用CSS Grid越多,使我更加確信,在其上添加抽象層沒有任何好處,CSS網格就是是嵌入瀏覽器的CSS佈局框架。
Q:CSS 網格爲用於生產環境準備好了嗎?
A:這取決於你的網站,你的網站是否要兼容IE,Opera mini,Blackberry browser,Baidu mobile等瀏覽器?若是回答是否認,你能夠直接用於生產環境。若是回答是確定,那麼你能夠在支持它的瀏覽器(不須要添加前綴的瀏覽器佔比:91.61%)使用它經過編寫@supports
CSS規則:
@supports (display: grid) {
div {
display: grid;
}
}
複製代碼
基本上,一個網格佈局中能夠分解爲兩個元素:容器(grid container)和項目(grid-items)。
從圖二中咱們能夠看到,網格容器就是一個行和列的集合。一行就是兩根連續的水平線之間的空間,一列就是兩根連續的豎線之間的空間。一行被稱爲一個軌道(track),對於列也同樣。所以網格軌道就是兩根平行的網格線之間的空間。
每個軌道能夠有一個或者多個網格單元。cell就是最小的、最基本的網格單元,它是四根相交的網格線之間的空間。若是咱們把多個網格單元組合起來就造成了一個網格區域,值得一提的是網格區域必須是一個矩形區域,例如咱們不能產生一個T形狀的網格區域。
網格線從1開始到任何編號你能夠顯示或者隱式的定義,最後的網格線編號能夠被設爲-1,而在它以前的網格線編號爲-2,依此類推,這個在稍後的例子中會很方便。在圖二中列網格線的編號是從1增長6(或者是從-6到-1),行的網格線編號是從1增長到5(或者是從-5到-1)。
網格線的編號能夠被顯示的定義若是你在CSS樣式中明確設置,它也能夠被隱式地設置若是它是被瀏覽器動態地生成。
最後要補充地是,網格單元能夠經過空格和間距分開,這些間距被稱爲「槽」(gutters),可是咱們通常把它們當成間距。
好了,這樣咱們能夠開始實現一些網格佈局。首先咱們討論網格容器可使用的全部屬性,而後再介紹一下關於網格項(item)的一些屬性。
在本節中,讓咱們考慮以下模板:
<div class="grid-container">
<div class="grid-item">grid item 1</div>
<div class="grid-item">grid item 2</div>
<div class="grid-item">grid item 3</div>
<div class="grid-item">grid item 4</div>
<div class="grid-item">grid item 5</div>
<div class="grid-item">grid item 6</div>
<div class="grid-item">grid item 7</div>
<div class="grid-item">grid item 8</div>
<div class="grid-item">grid item 9</div>
</div>
複製代碼
Display
CSS網格是使用display屬性的grid
值定義的 ,所以,使用上面的模板定義網格佈局,咱們應該這樣作:
.grid-containter {
display: grid;
}
複製代碼
咱們能夠經過使用grid-template-rows
和grid-template-columns
屬性定義網格的行和列:
.grid-container {
grid-template-columns: 1fr 1fr 1fr 1fr;
grid-template-rows: 1fr auto 2fr;
}
複製代碼
或者咱們可使用grid-template屬性首先定義grid-template-rows
而後定義grid-template-columns
(使用斜杆分隔):
.grid-container {
grid-template: 1fr auto 2fr / 1fr 1fr 1fr 1fr;
}
複製代碼
順便提一下,fr
是一個分數單位,所以1fr
就是可用空間的一個部分。
repeat
函數表示軌道(track)列表的一個重複片斷,所以咱們能夠獲得和上面同樣的模板經過以下代碼:
.grid-container {
grid-template: 1fr auto 2fr / repeat(4, 1fr);
}
複製代碼
閱讀文檔repeat 能夠了解怎麼使用auto-fit
和auto-fill
動態地添加軌道(track)。
minmax
函數定義了一個尺寸的範圍,該範圍大於或者等於最小值,小於或者等於最大值,咱們能夠將該函數和repeat一塊兒使用:
.grid-container {
grid-columns: repeat(3, minmax(100px, 1fr));
}
複製代碼
咱們可使用row-gap
給行與行之間設置間距,一樣也可使用column-gap
給列與列設置間距:
.grid-container {
row-gap: 5px;
column-gap: 10px;
}
複製代碼
咱們也可使用gap
屬性先定義行間距而後定義列間距:
.grid-container {
gap: 5px 10px;
}
複製代碼
若是row-gap
和column-gap
值是同樣的,咱們只須要指定一個值。
指定一個網格項在網格佈局中的開始和結束位置,咱們基本上使用四個屬性,讓咱們先看下它們的定義。
屬性 | 定義 |
---|---|
grid-row-start | grid-row-start屬性經過提供一個行、一個span或者什麼都不提供來指定網格行在網格中的開始位置(自動) |
grid-row-end | grid-row-end屬性經過提供一個行、一個span或者什麼都不提供來指定網格行在網格中的結束位置(自動) |
grid-column-start | grid-column-start屬性經過提供一個行、一個span或者什麼都不提供來指定網格列在網格中的開始位置(自動) |
grid-column-end | grid-column-end屬性經過提供一個行、一個span或者什麼都不提供來指定網格列在網格中的結束位置(自動) |
或者咱們也可使用這些屬性的簡寫形式:
屬性 | 定義 |
---|---|
grid-row | grid-row 屬性是grid-row-start 和grid-row-end 的簡寫屬性,用於指定網格行中網格項的大小和位置 |
grid-column | grid-column屬性是grid-column-start 和grid-column-end 的簡寫屬性,用來指定網格列中網格項的大小和位置 |
考慮一下咱們在本節開始時使用的標記,假設咱們想要第三個網格項佔用四個單元格而不是一個(咱們但願它跨越兩個網格列和兩個網格行),效果就像圖三同樣,咱們該怎麼作了?
咱們能夠像這樣實現:
// Grid container
.grid-container {
display: grid;
gap: 10px;
grid-template-columns: repeat(4, 1fr);
grid-template-rows: repeat(3, 1fr);
}
// Grid item (third)
.grid-container .grid-item:nth-child(3) {
grid-column-start: 1;
grid-column-end: 3;
grid-row-start: 1;
grid-row-end: 3;
// or
grid-column: 1 / 3;
grid-row: 1 / 3;
// or
grid-column: 1 / span 2;
grid-row: 1 / span 2;
// or
grid-column: -5 / span 2; // because we have 4 columns
grid-row: -4 / span 2; // because we have 3 rows
}
複製代碼
注意,第三個網格項其實就是圖三中的第一個,這與CSS網格能夠(第一次)擁有源碼順序獨立性有關。當咱們討論
grid-auto-flow
的時候,咱們還會講到這個知識點。
若是你想玩它,探索不一樣的解決方案,點擊這裏。
還有一些更高級的屬性能夠幫助您按照本身的須要調整模板。在這小節,咱們將學習這些屬性並知道如何在CSS中使用它們。
在這個小節,咱們考慮以下模板:
<div class="grid-container">
<div class="grid-item header">Header</div>
<div class="grid-item content">Content</div>
<div class="grid-item navbar">Navbar</div>
<div class="grid-item meta">Meta</div>
<div class="grid-item footer">Footer</div>
</div>
複製代碼
使用咱們前面學過的知識,咱們可使用以下的CSS樣式使得它看起來像一個基本的網站佈局:
.grid-container {
grid-template: repeat(6, 1fr) / repeat(12, 1fr);// rows then columns
}
.grid-container .header {
grid-column: 1 / -1;
grid-row: 1 / 2;
}
.grid-container .navbar {
grid-column: 1 / 2;
grid-row: 2 / -1;
}
.grid-container .content {
grid-column: 2 / -1;
grid-row: 2 / -2;
}
.grid-container .footer {
grid-column: 2 / -1;
grid-row: -2 / -1;
}
.grid-container .meta {
grid-column: -3 / -1;
grid-row: 2 / 4;
}
複製代碼
如今假設咱們想要導航條(在右邊)寬一點,目前,它跨越了一列,可是咱們想要它跨越兩列。爲了實現這個效果,咱們須要改變.navbar
的位置,同時也要改變.content
和.footer
的位置,由於當前.navbar
是從列1到列2,而.footer
和.content
是從列2一直到最後。
若是每次都要修改元素的位置,那就太單調了。若是有一種辦法來告訴CSS網格自動爲咱們去作這件事,那就太好了。固然,不止有一種方法能夠實現,至少有兩種方法。
第一種解決方案就是命名特定的行,而後咱們能夠用它的別名而不是它的編號來引用它,讓咱們嘗試實現它。
.grid-container {
grid-template-rows: repeat(6, 1fr);
grid-template-columns: 1fr 1fr [content-start navbar-end] repeat(10, 1fr);
}
複製代碼
在上面的代碼中,咱們使用包含別名的簡單方括號爲第三行命名(單一的行能夠有多個別名)。而後咱們修改前面提到的元素的CSS代碼:
.grid-container .navbar {
grid-column: 1 / navbar-end;
grid-row: 2 / -1;
}
.grid-container .content {
grid-column: content-start / -1;
grid-row: 2 / -2;
}
.grid-container .footer {
grid-column: content-start / -1;
grid-row: -2 / -1;
}
複製代碼
實現的效果像下面這樣:
嘗試對其它的行實現相同的效果(前面的:header-row-end / content-row-start
)能夠點擊下面的代碼片斷
第二種解決方案是使用模板區域,grid-template-areas
屬性用來指定命名的網格區域。這個屬性有個奇怪的CSS語法,但咱們像這樣使用它:
.grid-container {
grid-template-areas:
'h h h h h h h h h h h h'
'n n c c c c c c c c c c'
'n n c c c c c c c c c c'
'n n c c c c c c c c c c'
'n n c c c c c c c c c c'
'n n f f f f f f f f f f';
}
.grid-container .navbar {
grid-area: n;
}
.grid-container .content {
grid-area: c;
}
.grid-container .footer {
grid-area: f;
}
.grid-container .header {
grid-area: h;
}
.grid-container .meta {
grid-column: -3 / -1;
grid-row: 2 / 4;
}
複製代碼
咱們使用grid-template-areas
定義網格容器區域,而後使用grid-area
將網格項放置到須要的網格區域。值得注意的是,全部的區域必須是矩形。
注意,咱們沒有爲
.meta
元素使用grid-area
,這是由於,目前沒有可使用這種方式來疊加元素的方法,至少我不知道。
你能夠繼續玩它,可用的代碼點擊這裏。
考慮以下代碼:
<div class="grid-container">
<div class="grid-item">1</div>
<div class="grid-item">2</div>
<div class="grid-item">3</div>
<div class="grid-item">4</div>
<div class="grid-item">5</div>
<div class="grid-item">6</div>
</div>
<style> .grid-container { grid-template-columns: repeat(3, minmax(100px, 1fr)); grid-template-rows: 80px; } .grid-container .grid-item:nth-child(2) { grid-row: span 2; } .grid-container .grid-item:nth-child(3) { grid-column: span 3; } </style>
複製代碼
咱們有一個三列的網格,咱們想讓第二個網格項跨越兩行,第三個跨越三列,結果以下圖:
這看起來很糟糕,因此這裏發生了什麼?首先,第二個元素比一個元素稍微高了一點,由於咱們想要它高一倍,可是看起來根本不像是高了一倍的高度。一樣,從3到6的網格項也沒有第一個高。
這與咱們顯示的設置第一行CSS樣式有關:grid-template-rows: 80px
,而其它的行被隱式地建立了,所以,第二行幾乎是不可見的,由於它是空的,而其它行的大小取決於它們內容所須要的。
咱們能夠像下面代碼這樣使用grid-auto-rows屬性設置隱式建立的行高度來修復這個問題:
.grid-container {
grid-template-columns: repeat(4, minmax(100px, 1fr));
grid-template-rows: 80px;
grid-auto-rows: 100px;
}
複製代碼
這樣看起來就像下圖同樣:
這樣看起來好一點了,可是咱們仍然能夠作得更好。注意這些空白的空間,爲何咱們沒有使用它們放置網格4,5,6項,爲了作到這樣,咱們可使用grid-auto-flow
。
grid-auto-flow
屬性控制自動放置算法的工做方式,準確地指定自動放置的網格項如何流入網格,它能夠有多個參數(你能夠點擊這裏瞭解更多),可是在這裏,咱們關心的只有一個:dense
。這個值告訴瀏覽器將網格項放置在任何足夠大的空間:
.grid-container {
grid-auto-flow: dense; // default is row
}
複製代碼
這樣咱們的網格看起來就很漂亮了:
講到這裏,咱們須要處理大量的信息,可是有了這些知識,咱們涵蓋了大量的CSS網格屬性,所以咱們能夠愉快地在應用中使用CSS網格佈局。這篇文章是一系列文章中的第一篇,在下一篇中,咱們將使用網格實現三個實際的例子,所以跟上節奏。
我但願你一如既往地從文章中學到了有用的知識,快樂編程!