注:此文是我翻譯的第一篇技術文章。適合有必定CSS原生網格佈局使用經驗的開發者(讀前須要先去了解一下原生CSS網格的語法),原生CSS網格佈局(Native CSS grid)截止目前尚未被任何正式版本的瀏覽器實現。原文地址css
_如下是來自Oliver Williams的帖子. Oliver已經學習了至關長時間的原生CSS網格,能夠說是在CSS網格方面有必定的發言權。在這篇文章中,他將以非同尋常的思路分析本身的CSS網格佈局學習之路。我比較贊同他的想法,就是學習一門新技術的時候,把它們拆分紅比較小的單元塊並配上實例,一步一步的學習。這比直接學習網格佈局的全部東西要好太多了。html
瀏覽器原生CSS網格預計會在2017年年初獲得支持. 在這以前你須要在瀏覽器中開啓這個實驗性的功能 (Firefox實驗版默認是開啓的). Chrome Canary是當前最好的實現. 同時,火狐有一個很是好的插件叫CSS Grid Inspector, 它能顯示出網格的線,它是目前惟一能夠在瀏覽器中運行的此類工具。web
在 chrome的地址欄中輸入chrome://flags
, 找到 ‘實驗性網絡平臺功能’ 並開啓它. IE 和 Edge 實現的是一個比較老的網格標準,如今並不受支持。算法
相信我,很快你就能掌握它的.chrome
網格佈局只能像左邊那樣,以矩形的單元塊組合起來。並不能像右圖那樣,由一堆零散的多邊形(跟俄羅斯方塊那樣的塊)拼湊。瀏覽器
雖然網格佈局和彈性盒在某些方面起到類似的做用,並且你能夠發現,不少人用彈性盒來實現網格佈局,但這並非設計彈性盒的初衷。Jake Archibald的這篇博文值得一讀_Don't use flexbox for overall page layout。網絡
這篇博文大概的意思是:app
Flexbox(彈性盒)是爲一維佈局設計的(行或列)。框架
CSS網格是爲二維設計的.less
Rachel Andrews也 說過相似的話:
Flexbox(彈性盒)用於一維佈局 – 也就是行或者列. 網格用於二維佈局 – 也就是多行多列.
它們能夠很好的結合,你能夠往彈性容器中放入網格,也能夠在網格塊中加入flex元素
來看個例子吧。 咱們想在一個網格元素(grid item)裏垂直居中一段文字, 但咱們想要讓背景(圖片,顏色或漸變)覆蓋整個的網格區域。 咱們可使用align-items
屬性,並把它的值設爲center,可是若是這樣背景並不會填滿整個網格元素的區域。align-items
默認的值是 stretch
-你不改變它,始終會填滿整個空間的。咱們把網格元素設爲align-items:center
並把網格元素(grid item)設置爲一個彈性容器(flex container)。
.grid { align-items: stretch; } .griditem { display: flex; align-items: center; }
在小屏幕下,寫一個12列的網格,全部格子的跨度都12列。
你能夠用網格這樣作:
/* For small screens */ .span4, .span6, .spanAll { grid-column-end: span 12; } /* For large screens */ @media (min-width: 650px) { .span4 { grid-column-end: span 4; } .span6 { grid-column-end: span 6; } }
這樣的顯示效果是沒什麼錯誤的,當使用CSS網格,從新定義列數很是簡單。而且你能夠經過設置grid-column-end: -1;
來讓你的頁面始終是從左到右貫穿的。
/* For small screens */ .span4, .span6, .spanAll { grid-column-end: -1; }
在大屏幕上,你想要儘量的接近12列,可是在移動端,一行大概是1~4列。用media來改變grid-template-columns
是很是容易的。
.grid { grid-template-columns: 1fr 1fr; } @media (min-width: 700px) { .grid { grid-template-columns: repeat(12, 1fr); } }
有一些元素,咱們想讓它貫穿整個視口,好比像 header, footer,和一些大圖啥的。
對於小屏幕,咱們能夠這樣寫:
.wide { grid-column: 1 / 3; /* start at 1, end at 3 */ }
不幸的是,當咱們換到大屏的時候,一行12列,這些元素將僅僅佔滿前兩列,並不會佔滿12列,咱們須要定義新的grid-column-end
,而且把他的值設爲 13
. 這種方式比較麻煩,還有一種簡單的方式,grid-column: 1 / -1;
,這樣不論在什麼屏幕尺寸下,它們都是佔滿整行的了。就像下面這樣:
.wide, .hero, .header, .footer { grid-column: 1 / -1; }
See the Pen Easier media queries with -1 by CSS GRID (@cssgrid) on CodePen.
使用grid-template-areas
和grid-line-numbers
是兩種控制行數的屬性,你也能夠兩個同時用。你可使用那些隱含的行名去設置你的網格。
.grid { grid-template-areas: "main main sidebar sidebar"; }
這段代碼,咱們能獲得四個隱含名字,main-start, main-end, sidebar-start, 和 sidebar-end.
這可能頗有用,若是你想重疊內容,不管是在幾個網格區域或在一個特定分段的網格區域。
See the Pen implicit line names with grid areas by CSS GRID (@cssgrid) on CodePen.
就像給網格的行命名,特殊的行名能用於設置網格區域,語法是這樣的:
.grid { grid-template-areas: "header header header" "main main sidebar" "footer footer footer"; } 、
若是你的佈局設計(太多列的佈局!沒列都要起名字,可能還須要空元素)中有不少空的區域,這種寫法稍微有點麻煩。因此對於網格是有另外一種寫法的,在這種寫法中,名字是什麼無所謂,只要你合理利用到[name-start]
和 [name-end]
,也能達到本身的佈局目的。下面是一個例子:
.grid { display: grid; grid-template-columns: 20px 100px [main-start] 1fr [main-end] 100px 20px; grid-template-rows: 100px [main-start] 100px [main-end] 100px; } .griditem1 { background-color: red; grid-area: main; }
See the Pen Another way of defining grid-areas by CSS GRID (@cssgrid) on CodePen.
你可能並不想整個頁面都用這種方式佈局,可是若是你想要結合 grid-area
來肯定行數的話,它會很是適合。
雖然你能夠在CSS網格中使用任意尺寸的行或列,可是若是想要相等大小的格子並是響應式的,你就須要使用vmin單位了。
.grid { grid-template-columns: repeat(5, 20vw); grid-template-rows: repeat(5, 20vh); }
這種佈局在臺式電腦和筆記本上基本均可以完美顯示,可是在手機上,高度大於寬,內容將會溢出,產生出一個橫向的滾動條。Dudley Storey寫了篇blog說這件事the usefulness of a lesser-known css unit: vmin。這種方法,經過調整容器視口的百分比和內容位置,作到適配各類尺寸的屏幕。
.gridcontainer { display: grid; width: 100vw; height: 100vh; justify-content: center; align-content: center; grid-template-columns: repeat(5, 20vmin); grid-template-rows: repeat(5, 20vmin); }
See the Pen Boxy Layout with CSS Grid and vmin by CSS GRID (@cssgrid) on CodePen.
當咱們絕對定位一個網格元素的時候,這個元素會跑到它的容器中,咱們能夠用grid-column 和 grid-row來定位它。正常狀況下,絕對定位使元素脫離文檔流,它最適合的使用場景就是想要讓元素重疊,並不打亂其餘佈局元素。除非你爲每一個元素聲明grid-column-start
和 grid-row-start
,要否則即便使用了絕對定位,元素也是不會重疊的。
嘗試刪除這個例子中div的position: absolute;
,思考grid-column 和 grid-row的值,也能夠試試修改它們,你就明白是什麼意思了。
See the Pen preserving auto-placement with position: absolute by CSS GRID (@cssgrid) on CodePen.
若是你使用過彈性盒(flexbox)的order
屬性,那你已經知道一些相關的知識了。全部的網格元素都有一個默認的order值0。因此若是給一個網格元素設置 order: 1;
,這個元素將在全部元素的後面。 你能夠給order
屬性設置負值,讓它跑到全部item的前面。
See the Pen Order value by CSS GRID (@cssgrid) on CodePen.
想不想要整行隨着內容的寬度而變寬,直到他們達到最大寬度,這種狀況你可能想嘗試使用 minmax()
:
.grid { display: grid; grid-template-columns: repeat(3, minmax(1fr, 300px)); }
不幸的是,像上面這樣看似簡單,其實是不行的。若是max小於min的話,css會被忽略。在minmax()
中fr
不能使用。實際上實現這個需求很容易,在grid-template-columns
或 grid-template-rows
中使用auto
,這樣item就能夠隨着內容增大而變大了。 See the Pen The value of auto vs fr by CSS GRID (@cssgrid) on CodePen.
咱們能夠設置一個 max-width
:
.grid { display: grid; grid-template-columns: repeat(3, auto); } .item { max-width: 300px; }
See the Pen The limits of minmax by CSS GRID (@cssgrid) on CodePen.
minmax()
的運行方式和使用我尚未徹底想出來,雖然如此,我仍是寫了一篇文章(譯者注:Medium entitled是什麼我沒有理解清楚,原文:I wrote an entire post on Medium entitled) The One Thing I Hate About Grid.
有多種辦法供你選擇,若是你就想多寫點,你能夠給多行設置多個名字。
.grid { grid-template-columns: [col1-start] 1fr [col1-end col2-start] 1fr [col2-end]; }
最簡單的命名約定使用網格自動編號。不是去寫 [col2],而是寫爲col 2
.griditem1 { grid-column-start: col 2; }
和span
關鍵字組合使用,咱們就不用去寫column-start和column-end中的各類網格線數字了,這樣能直觀許多。
.grid { grid-template-columns: repeat(4, [col] 100px); } .griditem1 { grid-column: col 2 / span 2; }
想象一下一行上四等列這種佈局,使用百分比是多麼的容易grid-template-columns: 25% 25% 25% 25%
。
可是當想用grid-gap
屬性的時候那?若是設置grid-gap: 10px
,那麼這一行上將有三個空隙,每一個10px,總體的寬度就是100% + 30px,大於100%滾動條就出來了。雖然能夠經過計算來解決,可是若是使用fr,這太容易了grid-template-columns: 1fr 1fr 1fr 1fr
See the Pen fr unit vs percentage by CSS GRID (@cssgrid) on CodePen.
沒有辦法強制自動佈局算法留下一些行和列是空的。
grid-gap
可讓咱們設置內容間的距離。grid-row-gap
和grid-column-gap
能設置行或列之間的間隙,但是若是我想讓第一行和第二行相距10px,第二行和第三行相距50px,用現有的網格是無法實現的,除非建個空行佔位。
你可能見到過像下面這樣寫grid-template-area
的::
grid-template-rows: "header header header" "main main main" " . . ." "secondary secondary secondary" "footer footer footer";
應該提供一個比較聰明的辦法,讓佈局算法去作這件事。不幸的是,這樣寫也沒用。此語法簡單地表示,咱們不想將第三行變成一個命名的網格區域。但是grid-template-rows將仍然在那結束。
12列網格算是web design的默認配置了。Bootstrap引導你們用12列網格,致使不少框架都是12列網格。12既能被3整除也能被4整除,能讓咱們有更多種佈局擺放方式。1行12列,1行6列,1行4列,1行3列,1行2列
雖然有些人喜歡每個項目老是使用相同的網格,可是你應該去思考你真正須要的,有時候沒有必要有更多的列,你應該創建一個網格,對針對你的內容去佈局,而不是一個12列網格處處用。
看看這個例子 Gridset. Gridset是一個製做網格很是有用的工具, 可是原生CSS的網格不須要你使用任何工具,可是能夠看看它展現的一些良好的網格設計。
看看我寫的例子,CSS原生網格是多麼的自由啊:
See the Pen text layout with CSS Grid module by CSS GRID (@cssgrid) on CodePen.