在上篇——JavaScript五十問——對比來講CSS的Grid與FlexBox(上篇),我介紹了Flex的屬性與使用,今天咱們來總結一下Grid的具體使用方法,最後會結合Flex與Grid佈局講一講兩者的聯繫與不一樣。css
須要注意得是,Grid佈局與咱們以前所熟悉的css佈局思路有很大的不一樣,閱讀這篇文章以前,須要把咱們平時對css的刻板印象拋棄掉,準備接受知識的洗禮吧,少年!html
與 Flex 相同,Grid 也分爲容器與元素兩個概念;在一個 html 標籤中添加樣式:display:grid
或者display:inline-grid
,即構建了一個 Grid 的容器,裏面的 dom 元素即爲 Grid 元素。一樣,Grid 也分爲兩類屬性,分別裝載在容器與元素上,下面一一說明。css3
如下全部例子均基於或擴展於下面的HTML結構:segmentfault
<style> .container{ width:500px; background-color:#999; } .item{ width: 50px; background-color:#567; color:#fff; } </style> <div class="container"> <div class="item">1</div> <div class="item">2</div> <div class="item">3</div> <div class="item">4</div> <div class="item">5</div> </div>
Grid容器裏面有網格一系列的概念;聽着唬人,可是結合圖很容易理解。dom
水平方向有垂直方向的線段即爲網格線
wordpress
兩個相鄰的平行網格線之間的區域就是網格軌道
函數
四個相鄰邊組成的區域就是網格單元。佈局
fr
是Grid中特有表示尺寸
的單位,是分數——fraction
的縮寫,假設咱們如今有四個grid元素,每一個元素的寬度都是1fr,那麼每一個元素的實際寬度就是總寬度的1/4。學習
fr也能夠跟%,px 共同使用,他的計算規則就是刨去px與%的剩餘空間做爲fr分配空間,全部fr相加之和做爲分母,分子爲每一個元素對應的fr的值。(固然,在Grid語境下,咱們是不須要設置width屬性的,這樣說是爲了讓你們容易理解)。spa
這樣說來好像fr僅僅是%的另一種寫法,隨着個人介紹,你就會發現fr優於%的地方。
接下來,我仍是以腦圖爲思路介紹Grid的各個屬性。
grid-tempalte是三個屬性的簡寫,這三個屬性都是描述整塊區域即多個網格單元
的屬性。
grid-template-rows是描述橫向
的單元軌道屬性
的。能夠試想一下,咱們在一個Grid容器中,關於這個屬性,咱們關心的是什麼呢?無非就是這個容器中有多少行,每行的高度;因此,這個屬性就是讓咱們定義這些值得。先來看語法:grid-template-rows: <track-size> | <line-name> <track-size> ...;
這個屬性除了能夠定義軌道尺寸和個數以外,還容許咱們定義兩個軌道之間的網格線的名稱,至於他的做用,咱們先按下不表,先來看這個屬性是怎樣定義每一個軌道的尺寸和軌道個數的。
先來看一個例子:
.container{ grid-template-rows:200px auto 1fr 1fr 20%; grid-row-gap:10px;//定義軌道之間的間距 }
grid-template-rows定義了五個值,表示Grid容器裏面有五行,可使用任意的定義尺寸的方式,效果以下
其中auto
值就表示元素的實際佔用大小。
Grid分配空間首先計算除了fr對應軌道的尺寸,而後將剩餘尺寸按照比例分配給fr加持的元素。
以上,咱們在Grid容器裏定義了五行容器軌道,當咱們定義軌道過多時,可使用repeat函數來減小咱們的工做量,語法爲:grid-template-rows:repeat(n, size)
例子:
.container{ grid-template-rows:repeat(5,1fr); grid-row-gap:10px; }
上面就定義了五個網格軌道,每一個軌道的高度是Grid容器高度的1/5。
grid-template-columns 與 grid-template-rows使用方法是一致的,這兩個屬性共同做用於Grid容器,至關於把Grid容器分割爲m*n個子區域。
例子:
.container{ grid-template-rows:repeat(3,1fr); grid-template-columns: repeat(2, 1fr)
上面這個例子就會獲得六個均等分的子區域。
經過上面兩個屬性,相信你們對Grid佈局有一個基本的認識了,想必對Grid二維佈局的模式也有一些概念了,接下來纔是Grid精彩之處,震撼靈魂的地方!
上面兩個屬性分別設置Grid行屬性和列屬性,grid-template-areas是設置Grid區域的。所謂區域是由一個或多個行、列、單元組成的一篇區域。首先看一下語法:
.container { grid-template-areas: "<grid-area-name> | . | none | ..." "..."; }
其中grid-area-name
表示網格區域的名稱.
表示空的網格區域none
表示沒有定義網格區域
在咱們平時開發時,常常會出現上頭下尾中間兩欄佈局的狀況,下面咱們使用grid-template-areas完成這樣的佈局。
<style> .container{ display:grid; grid-template-rows:60px auto 60px; grid-template-columns:100px 1fr; grid-template-areas: "header header" "left right" "footer footer"; } .container .item:first-child{ grid-area: header; } .container .item:nth-child(2){ grid-area: left; } .container .item:nth-child(3){ grid-area: right; } .container .item:nth-child(4){ grid-area: footer; } </style> .container{ display:grid; grid-template-rows:60px 1fr 60px; grid-template-columns:100px 1fr; grid-template-areas: "header header" "left right" "footer footer"; } .container .item:first-child{ grid-area: header; } .container .item:nth-child(2){ grid-area: left; } .container .item:nth-child(3){ grid-area: right; } .container .item:nth-child(4){ grid-area: footer; } .container{ display:grid; grid-template-rows:60px 1fr 60px; grid-template-columns:100px 1fr; grid-template-areas: "header header" "left right" "footer footer"; } .container .item:first-child{ grid-area: header; } .container .item:nth-child(2){ grid-area: left; } .container .item:nth-child(3){ grid-area: right; } .container .item:nth-child(4){ grid-area: footer; } </style> <div class="container"> <div class="item">1</div> <div class="item">2</div> <div class="item">3</div> <div class="item">4</div> </div>
在Grid容器中,咱們定義了6個網格單元,使用grid-tempalte-areas
劃分了header footer left right 四片區域;而在grid元素
中,每一個元素使用grid-area
來指定元素所對應的grid區域。所以,咱們雖然劃分了6個單元,但可使用四個元素來表示。
是否是很神奇呢,更神奇的是,grid-area-name是支持中文定義的。
以上grid-template的子屬性就說完了,grid-template是以上那三個屬性的簡寫方式,語法以下:
grid-tempalte:<'grid-template-rows'> / <'grid-template-columns'>` `grid-tempalte:[ <line-names>? <string> <track-size>? <line-names>? ]+ [ / <explicit-track-list> ]?
例如上面的例子能夠這樣簡寫
grid-template: "header header" 60px "left right" 1fr "footer footer" 60px / 50px 1fr;
grid-gap用來描述Grid 區域之間間隙的尺寸大小。語法以下:
.container { grid-gap: <grid-row-gap> <grid-column-gap>; }
grid-gap是簡寫屬性,也能夠分別定義grid行間隔和grid 列間隔。
.container{ grid-row-gap:10px; grid-column-gap:10px; }
grid-gap與margin與padding不一樣,它不佔用當前元素的盒模型的位置。
上圖顯示的很清楚,3號元素的margin 與 padding 均爲零。
place-items
是 justify-items
和align-items
的簡寫方式
這兩個屬性分別定義了Grid元素
水平與垂直分佈方式。
語法以下:
justify-items: stretch | start | end | center; align-items: stretch | start | end | center;
對於這四個屬性,默認stretch,相信讀者在熟悉了Flex佈局後都不會陌生,這裏很少作解釋,直接看例子,以align-items 爲例:
.container{ display:grid; grid-template: "header header" 160px "footer footer" 160px / 160px 160px; height:500px; grid-row-gap:10px; grid-column-gap: 10px; }
首先定義四個grid單元,每一個單元的長寬均爲160px
接下來咱們更改align-items的值
align-items:stretch
align-items:center
align-items:start
align-items: end
爲了方便你們理解,我用紅框框出每一個Grid單元所佔用的空間。由此能夠看出,place-items屬性是用來代表一個元素在當前grid單元中的分佈方式,這個元素的拉伸,居中等都是以grid單元做爲參考的。
place-content一樣是一個簡寫屬性,它包括:justify-content 和 align-content,它表示grid元素在grid容器中的分佈方式,只有當grid容器中有剩餘空間的時候才起做用。
語法以下:
justify-content: stretch | start | end | center | space-between | space-around | space-evenly; align-content: stretch | start | end | center | space-between | space-around | space-evenly;
屬性值得含義同Flex;這裏再也不過多說明,讀者能夠自行驗證。
grid-auto-rows 和 grid-auto-columns;用於當實際的Grid的元素多餘劃分的Grid元素時,定義多餘Grid元素的長寬;
例如咱們在HTML裏面必定了五個Grid元素,可是在css中只定義了2*2的Grid單元,可使用grid-auto來定義多出來的軌道的尺寸。
grid-auto-flow的用法須要結合下面的元素屬性來講明。
兩個屬性是用來定義Grid元素列方向上的起始與終止位置。
語法格式爲:
grid-column-start: <number> | <name> | span <number> | span <name> | auto
其中:
number爲起止第幾條網格線
name 爲網格線的名稱
span <number>網格元素會跨越網格單元的數量
span <name> 當前的網格元素會在哪個網格線上開始or終止
注意 使用span 若是是start,表示這個從開始的位置跨過的grid單元,若是是end 表示這個元素覆蓋的grid單元。
grid-column是它們的簡寫方式,語法爲:
grid-column:grid-column-start / grid-column-end
grid-row屬性與grid-column用法一致,這裏不過多贅言,直接看例子:
.container{ display:grid; grid-template-rows:[rone]1fr[rtwo]3fr[rthree]1fr[rfour]; grid-template-columns: [cone]1fr[ctwo]5fr[cthree]2fr[cfour]; height:500px; } .item:first-child{ grid-column-start:1; grid-column-end:cfour; grid-row-start:rone; grid-row-end: 2; } .item:nth-child(2){ grid-column-start:1; grid-column-end:span 1; grid-row-start:rtwo; grid-row-end: span cthree; } .item:nth-child(3){ grid-column-start: ctwo; grid-column-end:4; grid-row-start:rtwo; grid-row-end: span cthree; } .item:nth-child(4){ grid-column-start:1; grid-column-end:4; grid-row-start:3; grid-row-end: span 4; }
效果:
首先在Grid容器中劃分出9個grid單元,這九個單元被六個網格線所分割,並給這六個網格線命名。在四個Grid元素中定義橫行的起始位置。
grid-row 與 grid-column結合使用,能夠起到與Grid-template-areas一樣的效果。
grid-area咱們在前面已經接觸過一部分了,他與Grid容器中的grid-template-areas一塊兒定義,也是grid-column與grid-row的簡寫屬性,語法爲:
grid-area: <name> | <row-start> / <column-start> / <row-end> / <column-end>;
name爲grid區域的名稱,與grid-tempalte-areas結合使用。
上面咱們的例子就能夠用grid-area表示:
.item:first-child{ grid-area:1/rone/2/cfour; }
justify-self定義Grid元素的水平佈局方式的,例如,咱們在Grid容器中定義justify-items的屬性爲默認屬性,而在某一個Grid元素中定義justify-self爲center,那麼其餘元素表現爲拉伸,這個元素則單獨表現爲居中。也就是說,justify-self在Grid容器中對應的屬性是justify-items。
語法爲:
.item { justify-self: stretch | start | end | center; }
align-self與justify-self一致,改變的是這個元素的垂直部署方式,與容器中align-items對應,
語法爲:
.container { align-self: stretch | start | end | center; }
因爲這四個屬性值已經在咱們的系列文章中出現屢次,這裏再也不多說。
plac-self是以上兩個屬性的簡寫方式,語法爲:
.container { place-items: <align-self> / <justify-self>; }
Grid的全部屬性已經介紹完畢了,在對Grid宇宙有了一個基本的認識後,咱們再回頭看一下Grid宇宙中出現的新尺寸單位——fr。
可能你們在剛剛結仇到fr這個單位時,都會認爲它是%的一個別名;可是,咱們來看最下面的例子:
咱們在Grid容器中劃分出四個Grid區域,並定義每一個區域的寬度爲25%,並定義每一個Grid元素之間的gap寬70px;
.container{ display:grid; grid-template-columns: repeat(4, 25%); grid-column-gap: 70px; }
效果以下:
很明顯,這裏元素溢出了。這種狀況是咱們不想看到的。
下面,咱們將25%替換爲1fr看一下效果:
效果對比很明顯。
而形成二者顯著區別的緣由是兩者的計算空間方式的不一樣。使用百分比它的分母是父元素的width或者height,而fr的分母是父元素中剩餘空間的尺寸;css會首先計算使用%和px定義的元素尺寸,剩下的空間再由fr元素進行比例分配。這就是使用fr不會出現元素溢出的狀況。固然咱們也可使用calc避免溢出的尷尬,可是兩種解決方案孰優孰略已經一目瞭然了。
Flex佈局與Grid佈局有不少類似的地方,例如justify-content和justify-items的用法。可是更多的是不一樣,最重要的是Grid開拓了二維
佈局的方式,相比於傳統的css佈局方式(Flex、bootstrp 12列),Grid開創了網格的概念,用戶能夠從橫縱
兩個方面部署元素。正是由於如此,在Grid宇宙中,傳統的css佈局、尺寸屬性就顯得格格不入了。而Grid佈局的二維特性所帶來的總體觀,使Grid在頁面級別
樣式上更加遊刃有餘。而Flex相比於Grid 更加適合小組件上的樣式開發,兩者並不衝突相信在Grid 與 Flex雙雙加持之下,必定會收穫更好的開發效果!
Grid佈局仍是一個較新潮的概念,我也是通常看資料學習,一邊分享,因爲缺乏實際的開發經驗,對於不少屬性的應用場景尚未很深刻的理解,故而有的屬性一筆帶過;若是我有理解不正確的地方,歡迎你們指正!
MDN:Grid Layout
張鑫旭:寫給本身看的display: grid佈局教程
知乎:CSS 新的長度單位 fr 你知道麼?