翻譯 | CSS網(wǎng)格(CSS Grid)布局入門

翻譯 | CSS網(wǎng)格(CSS Grid)布局入門

banner

CSS網(wǎng)格布局是瀏覽器Flexbox布局之后最重要的布局方式。我們可以忘記過(guò)去15年經(jīng)常使用的的各種“神奇數(shù)字”,hacks和一系列變通布局方案。網(wǎng)格布局提供了非常簡(jiǎn)單的聲明布局方式,之后再也不需要借助一些常見的主流css框架,也能減少很多手動(dòng)實(shí)現(xiàn)的布局方式

如果你以前不熟悉CSS網(wǎng)格布局,那么你可以開始了解它了。它是一種適用于容器元素,并能指定子元素的間距、大小和對(duì)齊方式的布局工具。

CSS網(wǎng)格布局賦予我們更強(qiáng)大的能力——大家熟悉的水平垂直居中布局,不需要增加標(biāo)簽就能做到。同樣,這也能讓我們不需要媒體查詢就能根據(jù)可用空間自動(dòng)適應(yīng)。

學(xué)習(xí)的最低要求

首先網(wǎng)格布局有不少新語(yǔ)法需要學(xué)習(xí),但是你只需要稍微看下就能上手。本文將會(huì)用示例帶你學(xué)習(xí)CSS網(wǎng)格布局各種各樣重要的入門概念。

瀏覽器兼容性

CSS網(wǎng)格布局從Safari 10.1, Firefox 52, Opera 44, Chrome 57開始收到支持,微軟Edge在Edge 15會(huì)更新對(duì)網(wǎng)格布局的支持。

微軟的瀏覽器(IE10–11和Edge 13-14)有一種比較舊的實(shí)現(xiàn),所以有不少限制,我們會(huì)簡(jiǎn)單介紹新的實(shí)現(xiàn)方式和老的實(shí)現(xiàn)方式之間的區(qū)別,這樣你能知道如何規(guī)避他們。

對(duì)于大多數(shù)布局,我們會(huì)使用下面的query特性來(lái)讓老的瀏覽器對(duì)他們理解的特性也能工作:

@supports (display: grid) {
    .grid {
        display: grid;
    }
}

不支持瀏覽器@supports或網(wǎng)格的瀏覽器將不會(huì)生效。

為了能正確展示文中的示例,你需要使用支持網(wǎng)格布局的瀏覽器。

創(chuàng)建帶有間距(gutter)的兩列(column)網(wǎng)格

為了演示CSS網(wǎng)格布局如何定義列,我們從下面的布局開始:


grid-template-columns 和 grid-gap

[使用grid-template-columns 和 grid-gap創(chuàng)建帶間距的兩列布局]

為了創(chuàng)建上述網(wǎng)格布局,我們需要使用grid-template-columnsgrid-gap。
grid-template-columns表示網(wǎng)格中的列是如何布局的,它的值是一連串以空格分割的的值,這些值標(biāo)識(shí)每列的大小,值的個(gè)數(shù)表示列的數(shù)目。

例如,四列250px寬度的網(wǎng)格布局可以這樣表示:

grid-template-columns: 250px 250px 250px 250px;

也可以使用repeat關(guān)鍵字表示:

grid-template-columns: repeat(4, 250px);

定義間距

grid-gap定義了網(wǎng)格布局的間距大小,接收一個(gè)或兩個(gè)值,如果定義兩個(gè)值則表示列(column)和行(row)的間距大小。

在兩列布局示例中,我們可以如下使用:

.grid {
  display: grid;
  grid-template-columns: 50vw 50vw;
  grid-gap: 1rem;
}

不幸的是,這個(gè)間距將會(huì)占用容器元素的整體寬度,計(jì)算出來(lái)就是100vw + 1rem,最終這個(gè)布局會(huì)導(dǎo)致出現(xiàn)水平滾動(dòng)條。

viewport導(dǎo)致的水平滾動(dòng)條

[通過(guò)viewport單位創(chuàng)建帶間距網(wǎng)格導(dǎo)致的水平滾動(dòng)條]

為了解決這個(gè)空間溢出問(wèn)題,我們需要些不同的方法來(lái)處理,需要用分?jǐn)?shù)單位或者說(shuō)是FR。

分?jǐn)?shù)單位

分?jǐn)?shù)單位標(biāo)識(shí)占用可用空間的份額,如果900px是可用空間,其中的一個(gè)元素占有1份,另外的元素占有2份——那么第一個(gè)元素的寬度會(huì)是900px的1/3,另外的元素是900px的2/3。
修改后用分?jǐn)?shù)代替view-port單位的新代碼如下:

.grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  grid-gap: 1rem;
}

內(nèi)容對(duì)齊

為了對(duì)齊示例中的內(nèi)容,我們?cè)谧釉厣鲜褂胓rid布局,并加上對(duì)齊屬性來(lái)定位他們到指定軌道(track),軌道就是一個(gè)網(wǎng)格的列或行的某個(gè)位置的常見的名稱。網(wǎng)格跟Flex布局一樣,有一系列對(duì)齊的屬性——共有四種值——start, center, end, 和stretch,分別對(duì)應(yīng)其子元素所在的軌道。stretch跟其他不太一樣,它會(huì)將元素從所在軌道的頭拉伸到尾。

align-items 和 justify-content

[align-items 和 justify-content]

例子中我們要將內(nèi)容水平和垂直居中,可以通過(guò)在容器上設(shè)置下面這些屬性:

.center-content {
    display: grid;
    align-items: center;
    justify-content: center;
}

示例地址

使用舊的網(wǎng)格布局實(shí)現(xiàn)兩欄布局

如果使用舊的網(wǎng)格布局方式創(chuàng)建,我們需要考慮實(shí)現(xiàn)中的諸多限制。舊的布局方式不僅沒(méi)有grid-gap,而且你需要在每一個(gè)網(wǎng)格元素上聲明網(wǎng)格元素的起始位置,否則默認(rèn)會(huì)設(shè)置為1,這樣所有的網(wǎng)格都會(huì)堆在第一列。

舊版本的布局方式需要通過(guò)增加間距作為網(wǎng)格軌道的一部分,也需要設(shè)置每個(gè)網(wǎng)格從哪里開始:

.grid-legacy {
   display: -ms-grid;
   -ms-grid-columns: 1fr 1rem 1fr; // 取代 gap 間距
}
.grid-legacy:first-child {
   -ms-grid-column: 1;
}
.grid-legacy:last-child {
    -ms-grid-column: 3;
}

舊的布局方式實(shí)現(xiàn)對(duì)齊和全高度

舊的布局方式跟IE 11中Flexbox有一樣的問(wèn)題,在容器上設(shè)置最小高度(min-height)不一定會(huì)生效。這個(gè)問(wèn)題通過(guò)網(wǎng)格布局來(lái)解決更方便。

為了實(shí)現(xiàn)這個(gè)效果我們?cè)诟溉萜鞯男袑傩陨鲜褂?code>minmax方法,minmax指定了行或列的最大和最小值。

-ms-grid-rows: minmax(100vh, 1fr);

在子元素上我們聲明一個(gè)單位為1fr的單列單行的網(wǎng)格:

.ms-cell {
   -ms-grid-columns: 1fr;
   -ms-grid-rows: 1fr;
}

最后,因?yàn)槲覀儾荒芟馞lexbox或最新網(wǎng)格布局那樣根據(jù)父元素對(duì)齊,我們必須使用元素自身的對(duì)齊方式來(lái)對(duì)齊:

.ms-align-center {
    -ms-grid-column: 1;
    -ms-grid-column-align: center; // 新型grid布局中的 align-self
    -ms-grid-row-align: center; // 新型grid布局中的 justify-self
}

舊的兩列布局示例

到此我們實(shí)現(xiàn)了如何創(chuàng)建列、實(shí)現(xiàn)間距、內(nèi)容對(duì)齊及對(duì)舊的網(wǎng)格布局的支持。接下來(lái)讓我們實(shí)驗(yàn)下如何通過(guò)grid實(shí)現(xiàn)內(nèi)邊距。

通過(guò)CSS網(wǎng)格實(shí)現(xiàn)內(nèi)邊距(Negative Space)

網(wǎng)格布局允許你通過(guò)grid-column-start屬性指定列開始的位置,所以就有了可以在網(wǎng)格內(nèi)創(chuàng)建內(nèi)邊距的可能性。

使用grid-template-columns和grid-column-start創(chuàng)建內(nèi)邊距

[使用grid-template-columns和grid-column-start創(chuàng)建內(nèi)邊距]

創(chuàng)建內(nèi)邊距的一種方式是在列的實(shí)際位置上設(shè)置一個(gè)數(shù)字,空出網(wǎng)格元素的原始空間, 網(wǎng)格元素也會(huì)被push到新的網(wǎng)格列。

grid-column-start push

[隨著grid-column-start push 第一項(xiàng)]

在上面的內(nèi)邊距示例中,html結(jié)構(gòu)中用一個(gè)div包裹另外一個(gè)div:

<div class="grid">
    <div class="child"><!-- 內(nèi)容 --></div>
</div

網(wǎng)格像這樣設(shè)置:

.grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
}

為了讓子元素從右側(cè)開始,我們?cè)O(shè)置子元素從第2列開始:

.child {
    grid-column-start: 2;
}

注意:在Firefox 52中的一個(gè)差異導(dǎo)致一個(gè)垂直對(duì)齊問(wèn)題——基于FR單位的行不會(huì)拉伸得跟整個(gè)窗口一樣高。為了解決(address)這個(gè)問(wèn)題我們?cè)O(shè)置子元素為網(wǎng)格項(xiàng),并給每一行設(shè)置一個(gè)想要的高度:

.l-grid--full-height {
    grid-template-rows: minmax(100vh, 1fr);
}

設(shè)置內(nèi)邊距示例

用內(nèi)容死區(qū)(content dead-zones)創(chuàng)建空白

在四列布局中,給本來(lái)在第三列的網(wǎng)格項(xiàng)上設(shè)置grid-column-start:2;,那么會(huì)找到下一個(gè)可用的第二列來(lái)填充空間。

網(wǎng)格軌道會(huì)跳過(guò)某些列,直到找到下一列。我們可以利用這個(gè)方法在網(wǎng)格內(nèi)創(chuàng)建空白,沒(méi)有內(nèi)容的網(wǎng)格也會(huì)被分配。
[創(chuàng)建空白示例]


[使用grid-template-columns 和 grid-column-start創(chuàng)建空白]

創(chuàng)建行

如果我們想分割布局為四份,我們目前所了解的關(guān)于列的布局方式對(duì)行同樣有效:

.grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    grid-template-rows: 250px 250px;
}

[同時(shí)使用grid-template-columns 和 grid-template-rows創(chuàng)建網(wǎng)格布局]

理想情況下這個(gè)示例是沒(méi)問(wèn)題的。因?yàn)榇藭r(shí)每個(gè)網(wǎng)格項(xiàng)的內(nèi)容足夠少而不會(huì)撐開每行。但隨著內(nèi)容的變化,一切都不一樣了。當(dāng)示例中的內(nèi)容超出指定行的大小后,看下會(huì)發(fā)生什么:


[內(nèi)容超出聲明的行高]

我們創(chuàng)建了250px高的兩行,如果內(nèi)容超過(guò)每行的高度,將會(huì)打破布局并和后面的行的內(nèi)容重疊。并不是一個(gè)我們想要的結(jié)果。

靈活的設(shè)置最小值

我們?cè)谠搱?chǎng)景下需要的是設(shè)置最小尺寸的能力,但又要允許尺寸可以根據(jù)內(nèi)容彈性變化。這里我們通過(guò)上面舊瀏覽器示例中的minmax關(guān)鍵字實(shí)現(xiàn)。

.grid {
    grid-template-rows: minmax(250px, auto) minmax(250px, auto);
}

創(chuàng)建有最小值的彈性行

現(xiàn)在我們已經(jīng)了解了創(chuàng)建帶有內(nèi)容的行的基礎(chǔ)方法,我們開始來(lái)創(chuàng)建水平和垂直交錯(cuò)的更復(fù)雜網(wǎng)格布局。


[使用grid-column-start和span關(guān)鍵字創(chuàng)建復(fù)雜網(wǎng)格布局Unsplash]

創(chuàng)建更復(fù)雜的網(wǎng)格

我們開始創(chuàng)建更復(fù)雜的網(wǎng)格布局。將網(wǎng)格中的每個(gè)網(wǎng)格項(xiàng)設(shè)置成占據(jù)多條軌道,在一列內(nèi),我們能通過(guò)grid-column-startgrid-column-end實(shí)現(xiàn),或者通過(guò)如下所示更簡(jiǎn)單的寫法:

grid-column: 1 / 3;

用這種實(shí)現(xiàn)方式的弊端是難以“模塊化”,為了定位每塊內(nèi)容需要寫很多代碼。span關(guān)鍵字更符合模塊化的思路,因?yàn)槲覀兡芊旁谌魏蔚胤?,讓網(wǎng)格來(lái)控制他。我們可以定義網(wǎng)格項(xiàng)的開始位置,及其占據(jù)的軌道數(shù):

.span-column-3 {
    grid-column-start: span 3;
}

任何添加該class的網(wǎng)格將會(huì)從其開始位置,占據(jù)三個(gè)軌道。

[通過(guò)span實(shí)現(xiàn)的復(fù)雜網(wǎng)格]

使用span設(shè)計(jì)一個(gè)布局

我們能設(shè)計(jì)一個(gè)多軌道布局,通過(guò)將布局分解為grid布局中的最小單元。本示例中的最小單位是圖中高亮的部分。


[通過(guò)最小網(wǎng)格單位結(jié)合span創(chuàng)建更大的網(wǎng)格]

圍繞最小單位,我們能靈活的使用span來(lái)創(chuàng)建一些有意思的布局,因?yàn)閟pan是可以疊加的——你可以結(jié)合列和行的軌道在網(wǎng)格中創(chuàng)建多層級(jí)。

不需要媒體查詢(media queries)的彈性網(wǎng)格

雖然上面說(shuō)到的例子能在可用空間內(nèi)適應(yīng)變化,但是沒(méi)有一個(gè)是專門為空間變化設(shè)計(jì)的。網(wǎng)格有兩個(gè)非常有用的特性來(lái)適應(yīng)可用空間的變化。這兩個(gè)屬性叫‘a(chǎn)uto-fit’和‘a(chǎn)uto-fill’,像下面這樣結(jié)合repeat functionminmax function使用:

grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));

這些值代替了repeat中的數(shù)字,并計(jì)算在每條軌道上會(huì)填充多少行或列。二者之間最大不同是當(dāng)一條軌道上空白的溢出時(shí)的他們的處理方式不同。

auto-fit嘗試在不導(dǎo)致列溢出的情況下,放置該列能處理的最大數(shù)量的重復(fù)元素。當(dāng)沒(méi)有足夠的空間來(lái)放置更多的元素時(shí),之后的元素將會(huì)放到下一行,不能填滿的空間將會(huì)被保留。

auto-fill

[示例:auto-fill. auto-fill會(huì)保留后面空間,反之a(chǎn)uto-fit會(huì)讓空白收縮為0px]

auto-fill的表現(xiàn)跟auto-fit類似,但是任何的空白空間都會(huì)自動(dòng)收縮,同時(shí)這一行的元素也會(huì)被拉升——類似flexbox的效果,列會(huì)隨著可用空間變小發(fā)生折疊。

grid-auto-fit示例

[grid-auto-fit示例]

依賴媒體查詢的布局跟窗口大小關(guān)系很大,這不夠模塊化——系統(tǒng)內(nèi)的組件應(yīng)該能根據(jù)可用空間自適應(yīng)。那么在實(shí)踐中會(huì)是什么樣的呢?

auto-fit

[grid auto-fit的真實(shí)示例]

[網(wǎng)格auto-fit示例]

這只是冰山一角

我們已經(jīng)經(jīng)歷了快十五年的CSS浮動(dòng)為主的布局方式,我們上面學(xué)習(xí)了幾乎所有你能用float實(shí)現(xiàn)的布局——CSS網(wǎng)格布局是這個(gè)領(lǐng)域的新代表,仍然還有許多東西需要去嘗試和學(xué)習(xí)。

現(xiàn)在最重要的步驟是開始使用它。在構(gòu)建、創(chuàng)建更多高級(jí)布局的時(shí)候會(huì)很方便。網(wǎng)格布局還有不少未知領(lǐng)域,一旦我們更好地理解其能力并開始與其他特性結(jié)合,我們便能用更少代碼創(chuàng)造更多有趣、靈活的布局,并能減少些框架抽象的麻煩。

如果你感興趣并想進(jìn)一步探究CSS網(wǎng)格,可以試下Rachel Andrew的例子,這里面通過(guò)帶解釋說(shuō)明的實(shí)例探討了CSS網(wǎng)格布局的每一個(gè)特性。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 簡(jiǎn)介 CSS Grid布局 (又名"網(wǎng)格"),是一個(gè)基于二維網(wǎng)格布局的系統(tǒng),旨在改變我們基于網(wǎng)格設(shè)計(jì)的用戶界面方式...
    咕咚咚bells閱讀 2,690評(píng)論 0 4
  • 簡(jiǎn)介CSS網(wǎng)格布局(又稱“網(wǎng)格”),是一種二維網(wǎng)格布局系統(tǒng)。CSS在處理網(wǎng)頁(yè)布局方面一直做的不是很好。一開始我們用...
    _leonlee閱讀 65,745評(píng)論 25 173
  • 前言 溫馨提示:本文較長(zhǎng),圖片較多,本來(lái)是想寫一篇 CSS 布局方式的,但是奈何 CSS 布局方式種類太多并且實(shí)現(xiàn)...
    sunshine小小倩閱讀 3,265評(píng)論 0 59
  • 問(wèn)答題47 /72 常見瀏覽器兼容性問(wèn)題與解決方案? 參考答案 (1)瀏覽器兼容問(wèn)題一:不同瀏覽器的標(biāo)簽?zāi)J(rèn)的外補(bǔ)...
    _Yfling閱讀 14,090評(píng)論 1 92
  • 第十四章 這一夜,二人從天界仙境,聊道凡塵人事,未曾刻意回避什么,不經(jīng)意提到,聊一聊,話題自個(gè)兒就偏到十萬(wàn)八千里之...
    若莎Elsa閱讀 7,597評(píng)論 1 52

友情鏈接更多精彩內(nèi)容