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

原文地址

注:此文是我翻譯的第一篇技術文章。適合有一定CSS原生網格布局使用經驗的開發者(讀前需要先去了解一下原生CSS網格的語法),原生CSS網格布局(Native CSS grid)截止目前還沒有被任何正式版本的瀏覽器實現。

_以下是來自Oliver Williams的帖子. Oliver已經學習了相當長時間的原生CSS網格,可以說是在CSS網格方面有一定的發言權。在這篇文章中,他將以非同尋常的思路分析自己的CSS網格布局學習之路。我比較贊同他的想法,就是學習一門新技術的時候,把它們拆分成比較小的單元塊并配上實例,一步一步的學習。這比直接學習網格布局的所有東西要好太多了。

瀏覽器原生CSS網格預計會在2017年年初得到支持. 在這之前你需要在瀏覽器中開啟這個實驗性的功能 (Firefox實驗版默認是開啟的). Chrome Canary是當前最好的實現. 同時,火狐有一個非常好的插件叫CSS Grid Inspector, 它能顯示出網格的線,它是目前唯一可以在瀏覽器中運行的此類工具。

在 chrome的地址欄中輸入chrome://flags, 找到 ‘實驗性網絡平臺功能’ 并開啟它. IE 和 Edge 實現的是一個比較老的網格標準,現在并不受支持。

網格布局不是將零散的塊拼到一起

相信我,很快你就能掌握它的.

網格布局只能像左邊那樣,以矩形的單元塊組合起來。并不能像右圖那樣,由一堆零散的多邊形(跟俄羅斯方塊那樣的塊)拼湊。

設計網格布局并不是為了取代彈性盒,相反,它是彈性盒的一種補充

雖然網格布局和彈性盒在某些方面起到相似的作用,而且你可以發現,很多人用彈性盒來實現網格布局,但這并不是設計彈性盒的初衷。Jake Archibald的這篇博文值得一讀_Don't use flexbox for overall page layout

這篇博文大概的意思是:

  • Flexbox(彈性盒)是為一維布局設計的(行或列)。

  • CSS網格是為二維設計的.

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;
}

給grid-column-end設置負值,意想不到的有用

在小屏幕下,寫一個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-areasgrid-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來確定行數的話,它會非常適合。

相等尺寸網格(equal sized box layout)使用vmin單位

雖然你可以在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-startgrid-row-start,要不然即使使用了絕對定位,元素也是不會重疊的。

嘗試刪除這個例子中div的position: absolute;,思考grid-column 和 grid-row的值,也可以試試修改它們,你就明白是什么意思了。

See the Pen preserving auto-placement with position: absolute by CSS GRID (@cssgrid) on CodePen.

改變網格元素(grid item)的順序

如果你使用過彈性盒(flexbox)的order 屬性,那你已經知道一些相關的知識了。所有的網格元素都有一個默認的order值0。所以如果給一個網格元素設置 order: 1;,這個元素將在所有元素的后面。
你可以給order屬性設置負值,讓它跑到所有item的前面。

See the Pen Order value by CSS GRID (@cssgrid) on CodePen.

grid中 minmax()的坑

想不想要整行隨著內容的寬度而變寬,直到他們達到最大寬度,這種情況你可能想嘗試使用 minmax()

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

不幸的是,像上面這樣看似簡單,實際上是不行的。如果max小于min的話,css會被忽略。在minmax()fr不能使用。實際上實現這個需求很容易,在grid-template-columnsgrid-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;
}

fr單位為什么那個的重要,讓你擺脫麻煩的計算

想象一下一行上四等列這種布局,使用百分比是多么的容易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-gapgrid-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將仍然在那結束。

Some design advice: You don't necessarily need 12 columns (and columns need not be uniform in size)

一些設計上的建議: 你不一點需要12列網格 (每一列不一定大小一致)

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.

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,572評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,071評論 3 414
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,409評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,569評論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,360評論 6 404
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,895評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 42,979評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,123評論 0 286
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,643評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,559評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,742評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,250評論 5 356
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 43,981評論 3 346
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,363評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,622評論 1 280
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,354評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,707評論 2 370

推薦閱讀更多精彩內容

  • 簡介 CSS Grid布局 (又名"網格"),是一個基于二維網格布局的系統,旨在改變我們基于網格設計的用戶界面方式...
    咕咚咚bells閱讀 2,530評論 0 4
  • 前言 溫馨提示:本文較長,圖片較多,本來是想寫一篇 CSS 布局方式的,但是奈何 CSS 布局方式種類太多并且實現...
    sunshine小小倩閱讀 3,151評論 0 59
  • 原文地址:Getting to know CSS Grid Layout 原文作者:Chris Wright 譯者...
    iKcamp閱讀 3,793評論 0 13
  • 簡介CSS網格布局(又稱“網格”),是一種二維網格布局系統。CSS在處理網頁布局方面一直做的不是很好。一開始我們用...
    _leonlee閱讀 65,113評論 25 173
  • 有一天你會遇到一個彩虹般絢麗的人,從此以后,其她人就不過是匆匆浮云。 當你第一眼看到就覺得她和你遇到的任何一個人...
    我和你的約定閱讀 235評論 0 0