CSS進階12-網(wǎng)格布局 Grid Layout

(注1:如果有問題歡迎留言探討,一起學(xué)習(xí)!轉(zhuǎn)載請注明出處,喜歡可以點個贊哦?。?br> (注2:更多內(nèi)容請查看我的目錄。)

1. 導(dǎo)讀

網(wǎng)格布局是由CSS3引入的一種新的布局方式,提供了強大的布局能力。我們先來看一下W3C對于它的描述。

This CSS module defines a two-dimensional grid-based layout system, optimized for user interface design. In the grid layout model, the children of a grid container can be positioned into arbitrary slots in a predefined flexible or fixed-size layout grid.

翻譯過來就是,這個CSS模塊定義了一個二維的基于網(wǎng)格的布局系統(tǒng),為用戶界面設(shè)計進行了優(yōu)化。在網(wǎng)格布局模型中,網(wǎng)格容器的子節(jié)點可以定位到預(yù)定義的可伸縮的或者固定大小的布局網(wǎng)格中的任意插槽中。

2. 簡介

(注:本節(jié)內(nèi)容不是規(guī)范性的)。
網(wǎng)格布局是一種新的CSS布局模型,它具有強大的能力來控制箱子及其內(nèi)容的大小和位置。與面向單軸的Flexible Box Layout不同,Grid Layout針對二維布局進行了優(yōu)化:在兩個維度中都需要對齊內(nèi)容。

Figure 1示例性的Flex布局示例

Figure2 示例性的網(wǎng)格布局示例

此外,由于能夠明確定位網(wǎng)格中的項目,網(wǎng)格布局允許在視覺布局結(jié)構(gòu)中進行戲劇性的轉(zhuǎn)換,而不需要相應(yīng)的標(biāo)記更改。通過將媒體查詢與控制網(wǎng)格容器及其子節(jié)點布局的CSS屬性相結(jié)合,作者可以使其布局適應(yīng)設(shè)備形狀因素,方向和可用空間的變化,同時保持演示文稿內(nèi)容的理想語義結(jié)構(gòu)。

雖然許多布局可以用Grid或Flexbox來表示,但它們都有其特色。網(wǎng)格強制執(zhí)行二維對齊,使用自上而下的布局方式,允許項目的顯式重疊,并具有更強大的跨越能力。Flexbox專注于軸內(nèi)的空間分布,使用更簡單的自下而上的布局方法,可以使用基于內(nèi)容大小的換行系統(tǒng)content-size–based line-wrapping system來控制其次軸,并依靠底層標(biāo)記層次來構(gòu)建更復(fù)雜的布局。預(yù)計這兩者都將成為CSS作者的寶貴和補充工具。

2.1 背景和動機

隨著網(wǎng)站從簡單的文檔發(fā)展到復(fù)雜的交互式應(yīng)用程序,文檔布局技術(shù)(例如浮動)不一定非常適合應(yīng)用程序布局。通過組合使用表格,JavaScript或?qū)Ω釉剡M行仔細(xì)測量,作者發(fā)現(xiàn)了實現(xiàn)所需布局的解決方法。適應(yīng)可用空間的布局通常很脆弱,并且在空間受到限制時導(dǎo)致反直覺行為。作為替代方案,許多Web應(yīng)用程序的作者選擇固定布局,無法利用屏幕上可用渲染空間的更改。

網(wǎng)格布局的能力解決了這些問題。它為作者提供了一種機制,使用一組可預(yù)測的大小調(diào)整行為將可用空間分配給列和行。然后,作者可以將其應(yīng)用程序的構(gòu)造塊元素精確定位和設(shè)置到由這些列和行的交叉點定義的網(wǎng)格區(qū)域grid area中。以下示例說明了網(wǎng)格布局的自適應(yīng)功能,以及它如何更清晰地分離內(nèi)容和樣式。

2.1.1 將布局調(diào)整為可用空間

網(wǎng)格布局可用于智能調(diào)整網(wǎng)頁中的元素的大小。下列例子表示一個游戲,其布局中包含五個主要組件:游戲標(biāo)題,統(tǒng)計區(qū)域,游戲板,評分區(qū)域和控制區(qū)域。作者的意圖是劃分游戲空間,使得:

  • 統(tǒng)計區(qū)域總是直接出現(xiàn)在游戲標(biāo)題下。
  • 游戲板顯示在統(tǒng)計和標(biāo)題的右側(cè)。
  • 游戲標(biāo)題和游戲板的頂部應(yīng)始終對齊。
  • 當(dāng)游戲達到最小高度時,游戲板的底部和統(tǒng)計區(qū)域的底部對齊。在所有其他情況下,游戲板將會擴展以充分利用所有可用的空間。
    *控件集中在游戲板下。
  • 得分區(qū)域的頂部與控制區(qū)域的頂部對齊。
    *得分區(qū)域在統(tǒng)計區(qū)域下方。
  • 得分區(qū)域與統(tǒng)計區(qū)域下方的控件對齊。


    Figuer 4 根據(jù)內(nèi)容大小和可用空間排列五個網(wǎng)格項目

    Figuer 5 由于可用空間增加導(dǎo)致網(wǎng)格增長

    以下網(wǎng)格布局示例顯示作者如何以聲明方式實現(xiàn)所有尺寸,放置和對齊規(guī)則。

/* EXAMPLE 1 */
/**
* Define the space for each [grid item](https://www.w3.org/TR/css3-grid-layout/#grid-item) by declaring the grid
* on the [grid container](https://www.w3.org/TR/css3-grid-layout/#grid-container)
*/
#grid {
  /**
 * Two columns:
 *  1. the first sized to content,
 *  2. the second receives the remaining space
 *     (but is never smaller than the minimum size of the board
 *     or the game controls, which occupy this column [Figure 4])
 *
 * Three rows:
 *  3. the first sized to content,
 *  4. the middle row receives the remaining space
 *     (but is never smaller than the minimum height
 *      of the board or stats areas)
 *  5. the last sized to content.
 */
  display: grid;
  grid-template-columns:
    /* 1 */ auto
    /* 2 */ 1fr;
  grid-template-rows:
    /* 3 */ auto
    /* 4 */ 1fr
    /* 5 */ auto;
}

/* Specify the position of each [grid item](https://www.w3.org/TR/css3-grid-layout/#grid-item) using coordinates on
 * the 'grid-row' and 'grid-column' properties of each [grid item](https://www.w3.org/TR/css3-grid-layout/#grid-item).
 */
#title { grid-column: 1; grid-row: 1; }
#score { grid-column: 1; grid-row: 3; }
#stats { grid-column: 1; grid-row: 2; align-self: start; }
#board { grid-column: 2; grid-row: 1 / span 2; }
#controls { grid-column: 2; grid-row: 3; justify-self: center; }

<div id="grid">
  <div id="title">Game Title</div>
  <div id="score">Score</div>
  <div id="stats">Stats</div>
  <div id="board">Board</div>
  <div id="controls">Controls</div>
</div>

注意:有多種方式可以指定網(wǎng)格的結(jié)構(gòu)以及網(wǎng)格項目grid items的位置和大小,每個網(wǎng)格項每種場景都進行了優(yōu)化。

2.1.2 源順序獨立性 Source-Order Independence

繼續(xù)前面的例子,作者還希望游戲適應(yīng)不同的設(shè)備。此外,當(dāng)縱向或橫向觀看時,游戲應(yīng)該優(yōu)化組件的放置(Figuer6和7)。通過將網(wǎng)格布局與媒體查詢相結(jié)合,作者能夠使用相同的語義標(biāo)記,但可以重新排列元素的布局,而不是獨立于源順序,從而在兩個方向上實現(xiàn)所需的布局。


FIguer 6 適合“肖像”方向的布局

Figuer 7 適合“風(fēng)景”定位的布局

以下示例使用網(wǎng)格布局的能力來命名將被網(wǎng)格項grid item占據(jù)的空間。這允許作者避免在網(wǎng)格的定義改變時為網(wǎng)格項目重寫規(guī)則。

/* EXAMPLE 2 */

@media (orientation: portrait) {
  #grid {
    display: grid;

    /* The rows, columns and areas of the grid are defined visually
     * using the grid-template-areas property.  Each string is a row,
     * and each word an area.  The number of words in a string
     * determines the number of columns. Note the number of words
     * in each string must be identical. */
    grid-template-areas: "title stats"
                         "score stats"
                         "board board"
                         "ctrls ctrls";

    /* The way to size columns and rows can be assigned with the
     * grid-template-columns and grid-template-rows properties. */
    grid-template-columns: auto 1fr;
    grid-template-rows: auto auto 1fr auto;
  }
}

@media (orientation: landscape) {
  #grid {
    display: grid;

    /* Again the template property defines areas of the same name,
     * but this time positioned differently to better suit a
     * landscape orientation. */
    grid-template-areas: "title board"
                         "stats board"
                         "score ctrls";

    grid-template-columns: auto 1fr;
    grid-template-rows: auto 1fr auto;
  }
}

/* The grid-area property places a grid item into a named
 * area of the grid. */
#title    { grid-area: title }
#score    { grid-area: score }
#stats    { grid-area: stats }
#board    { grid-area: board }
#controls { grid-area: ctrls }



<div id="grid">
  <div id="title">Game Title</div>
  <div id="score">Score</div>
  <div id="stats">Stats</div>
  <div id="board">Board</div>
  <div id="controls">Controls</div>
</div>

注:網(wǎng)格布局的重新排序功能特意僅針對視覺渲染,而不影響基于源順序的語言順序和導(dǎo)航。這使得作者可以操作視覺呈現(xiàn),同時保持源順訊的完整性并針對非CSS UA和線性模型(如語言和順序?qū)Ш剑┻M行優(yōu)化。
注:網(wǎng)格項目的放置和重新排序不能用于替代正確的源排序,因為這可能會破壞文檔的可訪問性。

3. 瀏覽器的兼容性

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

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

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

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

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

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

4. 網(wǎng)格布局概念和術(shù)語

在網(wǎng)格布局中,一個網(wǎng)格容器的內(nèi)容排列是依靠于他里面網(wǎng)格的位置與對齊方式。網(wǎng)格是由水平和垂直網(wǎng)格比交織組成,他將網(wǎng)格容器的空間分為網(wǎng)格區(qū)域,網(wǎng)格項目將放置在這些網(wǎng)格區(qū)域中。在網(wǎng)格中有兩套網(wǎng)格線:一套是沿著水平方向的軸定義列的網(wǎng)格張,另一套是沿著垂直方向的軸定義行。


Figure 8 網(wǎng)格線:三個塊軸和四個內(nèi)嵌軸

4.1 網(wǎng)格線 Grid Lines

網(wǎng)格線是網(wǎng)格的水平和垂直的分界線。一個網(wǎng)格線存于行或列的兩側(cè)。他們可以參后數(shù)值指數(shù),也可以由設(shè)計師指定名稱。一個網(wǎng)格項目引用網(wǎng)格線來確定其網(wǎng)格中的位置屬性。

下面兩個例子創(chuàng)建了三個列網(wǎng)格線和四行網(wǎng)格線。第一個示例演示了設(shè)計師如何將一個使用網(wǎng)格行號的位置來確定網(wǎng)格項目的位置,第二個例子顯式的設(shè)置了網(wǎng)格線。

/*具有三個列網(wǎng)格線和四個行網(wǎng)格線*/   
#grid {
  display: grid;
  grid-definition-columns: 150px 1fr; /*兩列*/
  grid-definition-rows: 50px 1fr 50px;/*三行*/
}

#item1 { 
  grid-column: 2;
  grid-start: 1; 
  grid-end: 1; 
}   
/* 使用命名行,實現(xiàn)先前例子相等效果布局 */
#grid {
  display: grid;
  grid-definition-columns: 150px "item1-start" 1fr "item1-end";
  grid-definition-rows: "item1-start" 50px 1fr 50px "item1-end";
}

#item1 {
 grid-column: "item1-start" / "item1-end";
 grid-row: "item1-start" / "item1-end";
}   

4.2 網(wǎng)格軌道和單元格 Grid Tracks and Cells

網(wǎng)格軌道是“grid column”或者“grid row”的另一種術(shù)語,換句話說,他就是兩條相鄰網(wǎng)格線之間的空間。每個網(wǎng)格軌道可以設(shè)置一個大小,用來控制寬度或高度或者行可能會增長。
網(wǎng)格單元是網(wǎng)格行和網(wǎng)格列的交集。它是定位網(wǎng)格項時可以引用的網(wǎng)格的最小單元。
在接下來的例中定義了一個三行兩列的網(wǎng)格。第一列設(shè)置一個固定寬度“150px”,第二列設(shè)置是一個彈性尺寸,它是一個未賦值的網(wǎng)格空間,從而根據(jù)網(wǎng)格容器的變化而進行寬度的改變。如果網(wǎng)格容器的寬度是“200px”,那么第二列的寬度是“50px”。

#grid {
  display: grid;
  grid-definition-columns: 150px 1fr; /* 兩列*/
  grid-definition-rows: 50px 1fr 50px /* 三行  */
}   

4.3 網(wǎng)格區(qū)域 Grid Areas

網(wǎng)格區(qū)域是一個邏輯空間,主要用來放置一個或多個網(wǎng)格項目。他有四條網(wǎng)格線,網(wǎng)格區(qū)域每邊一條,四邊相交組織的網(wǎng)格軌道可以調(diào)整網(wǎng)格區(qū)域大小。可以使用“grid-template”屬性為網(wǎng)格容器顯式的設(shè)置網(wǎng)格區(qū)域,或者隱式的使用網(wǎng)格線創(chuàng)建網(wǎng)格區(qū)域。網(wǎng)格項目可以使用“grid-placement”屬性將其分配給一個網(wǎng)格區(qū)域。

#grid  {
  display: grid;
  grid-template: ". a"
                 "b a"
                 ". a";
  grid-definition-columns: 150px 1fr;
  grid-definition-rows: 50px 1fr 50px
}

#item1 { grid-area: a }
#item2 { grid-area: b }
#item3 { grid-area: b }

#item2 { align-self: head }
#item3 { justify-self: end; align-self: foot }   

4.4 網(wǎng)格容器 Grid Containers

通過“display”屬性給一個元素顯式的設(shè)置了“grid”或者“inline-grid”屬性值,這個元素將自動變成網(wǎng)格容器

一個網(wǎng)格容器將會創(chuàng)建一個新的網(wǎng)格格式化上下文內(nèi)容(grid formatting context)。除是網(wǎng)格布局代替了塊布局之外,網(wǎng)格格式化上下文和塊格式化上下文是相同的。浮動對網(wǎng)格容器不會有影響,而且網(wǎng)格容器的margin不會和內(nèi)容的margin相互層疊。

因為網(wǎng)格容器不是塊容器,所以一些屬性在網(wǎng)格布局中將會失效:

  • 多欄布局模塊中的所有“column-*”屬性運用在網(wǎng)格容器上將失效。
  • “float”和“clear”使用在網(wǎng)格項目上將失效
  • “vertical-align”使用在網(wǎng)格項目上將失效
  • “::first-line”和“::first-letter”這樣的偽元素不能應(yīng)用在網(wǎng)格容器上。
    注意:如果一個元素指定了“display”值為“inline-grid”,并且此元素具有“float”或絕對定位時,這個元素將的“display”值將會以“grid”顯示。

4.5 子網(wǎng)格容器 Subgrids

有時候我們需要給網(wǎng)格項目設(shè)置為網(wǎng)格容器。那么我們可以使用“display:grid”,在這種情況之下,他是獨立于網(wǎng)格布局的。而在某些情況下,要為內(nèi)容設(shè)置多個網(wǎng)格,讓網(wǎng)格項目相互一致,在這種情況之下,我們需要通過“dsplay”屬性顯式的設(shè)置為“subgrid”,讓其顯示為次網(wǎng)格。

例如,我們一個標(biāo)簽和輸入框組成的列表表單:

<ul>
  <li><label>Name:</label> <input name=fn></li>
  <li><label>Address:</label> <input name=address></li>
  <li><label>Phone:</label> <input name=phone></li>
</ul>   

我們希望這個標(biāo)簽和輸入文本框?qū)R,我們想給每個列表標(biāo)簽設(shè)置一個邊框樣式,這次就可以通過次網(wǎng)格布局實現(xiàn)。
ul {
display: grid;
grid-auto-flow: rows;
grid-definition-columns: auto 1fr;
}
li {
display: subgrid;
margin: 0.5em;
border: solid;
padding: 0.5em;
}
label {
grid-column: 1;
}
input {
grid-column: 2;
}

4.6 網(wǎng)格項目 Grid Items

在一個網(wǎng)格容器中包含了0個多個網(wǎng)格項目。網(wǎng)格容器的子元素稱為網(wǎng)格項目以及運行在網(wǎng)格容器的文本將自動變成一個匿名的網(wǎng)格項目,然后如果只是一個空格,這個匿名項目就相當(dāng)于“display:none”一相被隱藏在網(wǎng)格容器之中。

一個網(wǎng)格項目創(chuàng)建一個新的格式化上下文內(nèi)容。這種格式化上下文內(nèi)容類型取決于它的“display”值。

4.7 網(wǎng)格項目順序order

網(wǎng)格項目順序可以像flexobx模塊一樣,通過order屬性來對網(wǎng)格項目進行順序的重排。

5. 基本示例

以下示例顯示了一個三列軌道網(wǎng)格,其中創(chuàng)建的行最小為100像素,最大為自動。條目使用線性定位放置在網(wǎng)格上。

.wrapper {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-gap: 10px;
  grid-auto-rows: minmax(100px, auto);
}
.one {
  grid-column: 1 / 3;
  grid-row: 1;
}
.two { 
  grid-column: 2 / 4;
  grid-row: 1 / 3;
}
.three {
  grid-row: 2 / 5;
  grid-column: 1;
}
.four {
  grid-column: 3;
  grid-row: 3;
}
.five {
  grid-column: 2;
  grid-row: 4;
}
.six {
  grid-column: 3;
  grid-row: 4;
}



<div class="wrapper">
  <div class="one">One</div>
  <div class="two">Two</div>
  <div class="three">Three</div>
  <div class="four">Four</div>
  <div class="five">Five</div>
  <div class="six">Six</div>
</div>

參考

https://www.w3.org/TR/css3-grid-layout/#grid-formatting-context
前端精選文摘:css之GFC 神奇背后的原理(整理)
Getting to know CSS Grid Layout
翻譯 | CSS網(wǎng)格(CSS Grid)布局入門
MDN-網(wǎng)格布局
MDN-CSS Grid Layout

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

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

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 178,996評論 25 709
  • 問答題47 /72 常見瀏覽器兼容性問題與解決方案? 參考答案 (1)瀏覽器兼容問題一:不同瀏覽器的標(biāo)簽?zāi)J(rèn)的外補...
    _Yfling閱讀 14,125評論 1 92
  • 01 每個人最開始都會對生活和自己給予厚望,這種希冀不是別人強加給你,而是你內(nèi)心由衷的渴望。 但被生活戲虐一番后,...
    活在地球的貓閱讀 642評論 0 2
  • I don't really like fast food, beacause there are too man...
    yiyi1013閱讀 231評論 0 0
  • 自從2013年開始踏出校園,我差不多是馬上參加了工作,到去年我工作已經(jīng)兩年了。工作中難免會有出錯,誰都是從不...
    活力檸檬閱讀 273評論 7 6

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