二維 grid 佈局

本文摘自:please call me HRcss

so,first question? 啥是 grid 佈局?
grid 佈局是針對 Web 佈局的一個升級版,首先,回想一下,咱們寫 HTML 的時候,一個一個 div 像搭積木同樣,完成咱們最後的網頁。固然,咱們還須要使用 CSS 來配置咱們每一個 DOM 元素的具體位置,好比 navbar,sidebar 等等。有時候還要用各類 trick 才能知足咱們想要的佈局結果。但爲啥總感受不爽... 我就只想要這個元素放到指定位置而已,有這麼難嗎?web

有的面試

固然,你可使用 absolute 來完成,但這樣形成的性能損耗我就很少說了,問題是,你調位置估計就要哭在哪。。。爲啥? 太複雜了。。。按照圖形學來講,若是有一個座標讓我佈局,那就行了。 so, grid 就這樣誕生了。經歷了 flexbox 的一維佈局,grid 咱們就能夠用一句話表達:算法

grid 是網頁的二維佈局方式chrome

ok, let's start。因爲 grid 的支持性真的很渣。。。因此使用時須要額外開啓實驗室特性,在 Chrome 中,打開 chrome://flags 開啓實驗特性便可。首先,咱們來了解一下關於 grid 的基本概念。ide

grid 概念

grid 的內容其實和 table,flexbox 差很少。至關於二者的結合產物。一般,直接經過 display:grid; 來使用。最最基本的格式爲:函數

<div class="container" style="display:grid;">
  <div class="item item-1"></div>
  <div class="item item-2"></div>
  <div class="item item-3"></div>
</div>

這裏就包含了兩個最基本的概念。佈局

container 和 items

container 就是使用 display:grid 的 DOM。items 就是 container 包裹的一級子元素。記住:二級子元素就和 grid 不要緊!
而後,剩下的就是和 table 相似的屬性了。性能

line 和 cell

這個就比較好解釋了,先看圖吧:測試

這是 grid_line

grid_line

這是 grid_cell

grid_cell

固然,還沒完,接着就是 repeat cell 事後的理念。

track 和 area

track 至關於就是 行或者列。area 就是多個 cell 組成的面積。

這是 track

grid_track

這是 area

grid_area

grid 基本佈局

grid 的強大之處在於,他能夠將網頁劃分爲不少小格子,而你能夠將你的 DOM 隨意的放在你想放的格子裏面。還有一個必需要記住的點:

column, float, clear, 和 vertical-align 在 grid 佈局中是沒有效果的!

咱們先來看個 demo:
請問,你能在 5min 以內實現下列布局嗎?

grid_area

word哥。。。在沒有接觸到 grid 以前,我最早想到的就是使用 flexbox 來實現。並且須要 8 個 div。並且尼瑪就 5min。要是遇到這樣的面試題,我估計就直接噴面試官了。。。MDZZ。 但,面試官總會顯現他蜜汁微笑說,這,不,是,很,簡,單,嗎?
是的,使用 grid 佈局,真的很簡單。看下實際代碼也就幾行:

// HTML
<div id="container">
    <div class="column-1">one</div>
    <div class="column-2">two</div>
    <div class="column-3">three</div>
    <div class="column-4">four</div>
    <div class="column-5">five</div>
</div>

// CSS 部分
body {
    min-width: 550px;

}
#container{
    height: 200px;
    display: grid;
    grid-template-columns:1fr 1fr 1fr 1fr;
    grid-template-rows:1fr 1fr 1fr;
    grid-template-areas:"one one two three"
    "four four two three"
    "five five five three";
}
.column-1{
    grid-area:one;
    background-color: #F8594C;
}
.column-2{
    grid-area:two;
    background-color: #FFA29B;
}
.column-3{
    grid-area:three;
    background-color: #318B98;
}
.column-4{
    grid-area:four;
    background-color: #E73123;
}
.column-5{
    grid-area:five;
    background-color: #ABE646;
}

完整的實例能夠參考: grid 佈局

能夠說,grid 就是讓你用張紙畫幾個網格,而後填充,而後網頁就作好了。若是你想要動效的話,使用 animation 就 ok。啊~ 真簡單。。。 接下來,咱們來詳細的看一下 grid 裏面有哪些屬性標籤。權威指南請參考: MDN grid layout

grid 標籤講解

grid 的標籤能夠細分爲兩類:一類是屬於 container,一類是數據 items。
各有:

  • container:

    • grid-template-columns

    • grid-template-rows

    • grid-template-areas

    • grid-template

    • grid-auto-columns

    • grid-auto-rows

    • grid-auto-flow

    • grid

    • grid-column-gap

    • grid-row-gap

    • grid-gap

    • justify-items

    • align-items

    • justify-content

    • align-content

  • items:

    • grid-column-start

    • grid-column-end

    • grid-row-start

    • grid-row-end

    • grid-column

    • grid-row

    • grid-area

    • justify-self

    • align-self

看起來蠻多的,不過細分下來就幾個: template,auto,gap,佈局(content/items)
這裏,咱們就按上面的分類來說解。首先是 container 分類部分:

container

template

container 中的 template 有三種(還有一個是綜合標籤):columns,rows,areas。咱們先來看下 columns 和 rows。

grid-template-columns/rows

基本格式爲:

grid-template-columns: <track-size> ... | <line-name> <track-size> ... | subgrid;
 grid-template-rows: <track-size> ... | <line-name> <track-size> ... | subgrid;

也就是說,該標籤中屬性仍是蠻多的。咱們簡單介紹一下:

  • track-size:不管是 column 仍是 row,都是用來定義行高/列寬。取值能夠爲 px,%,auto,fr。重點說一下 auto 和 fr。 auto 和 其餘兩個屬性結合起來纔有效,表示自動充滿剩下的空間。 fr 就是 free space 的意思,用來表示是否均分剩下的空間。

  • line-name:用來設置行/列 line 的名稱。這個結合 item 中的 grid-row 有效。不設置的話,默認爲 1,2,3,4...

  • subgrid:嵌套 grid 時有效。暫不在討論的範圍以內。

看實例吧:
設置以下屬性值:

.container{
  grid-template-columns: 40px 50px auto 50px 40px;
  grid-template-rows: 25% 100px auto;
}

能夠獲得:

grid_line

至關於每一個值都表明行/列寬,百分數的值相對於 container 的寬度來的。繼續,咱們加上 line-name 來試一試:

.container{
  grid-template-columns: [first] 40px [line2] 50px [line3] auto [col4-start] 50px [five] 40px [end];
  grid-template-rows: [row1-start] 25% [row1-end] 100px [third-line] auto [last-line];
}

grid_line_name

感受定義了 line-name 以後,會有點複雜。咱們能夠這樣記憶,值抽象爲就是行/列,左右兩側就是線。這樣感受是否是好一點了?
fr 的話,就比較簡單了,均分操做:

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

另外, css 還提供了一個 repeat 函數,來幫助咱們快速書寫一樣格式的樣式:

// 使用 repeat
grid-template-columns: repeat(3, 20px [col-start]) 5%;

// 等同於
 grid-template-columns: 20px [col-start] 20px [col-start] 20px [col-start] 5%;

另外,咱們還可使用簡寫形式,將 columns 和 rows 寫在一塊兒。

// 基本格式就是: row / column / area
grid-template:repeat(4,1fr) / repeat(3,1fr);

接下來是 grid-template-areas。該屬性一般和 items 中的 grid-area 結合一塊兒使用。

grid-template-areas

他的基本格式爲:

grid-template-areas: "<grid-area-name> | . | none | ..."
                       "..."

記住,areas 寫的時候,注意是能夠分行寫的,這點極其重要。由於這能夠對應於每一個網格的 name 。基本取值爲:

  • grid-area-name:至關於給每一個 cell 取名字,好比 header,footer,body 等等。

  • . : 將該單元格設置空值。就是啥也沒有的意思。連名字也沒有,那麼就至關於將該 cell 設爲 empty。

  • none:是真的啥也沒有,當和 grid_name 混合使用時,和 . 沒啥太大的區別。但關鍵在於,他一般用於單獨定義的。

記住,該屬性必須和 item 中的 grid-area 纔有效果,具體的使用就是我上面的 demo:

#container{
    height: 200px;
    display: grid;
    grid-template-columns:1fr 1fr 1fr 1fr;
    grid-template-rows:1fr 1fr 1fr;
    grid-template-areas:"one one two three"
    "four four two three"
    "five five five three";
}
.column-1{
    grid-area:one;
    background-color: #F8594C;
}
.column-2{
    grid-area:two;
    background-color: #FFA29B;
}
...

總體效果如: grid-template-area

gap

grid 中 gap 相關的有兩個:grid-column-gap,grid-row-gap。這很好理解,就是用來設置行/列間隙。基本格式也是很簡單:

grid-column-gap: <line-size>;
  grid-row-gap: <line-size>;
  • line-size:基本 web 中的長度單位均可以使用,好比 px,vh,em,rem,auto 等等。不過比較遺憾的是,他不能設置每個行/列間隔的大小。

好比:

.container{
  grid-column-gap: 10px;
  grid-row-gap: 15px;
}

grid_gap

另外還有一個綜合單位就是: grid-gap。它其實就是上面兩個的綜合。基本形式爲:

grid-gap: <grid-column-gap> <grid-row-gap>;

接下來咱們來看一下 auto 系列。

auto

auto 包含的內容和 gap 差異不大,不過,他包含的是 3 個 tag:

grid-auto-columns: <track-size> ...;
grid-auto-rows: <track-size> ...;
grid-auto-flow: row | column | row dense | column dense

咱們先說一下前兩個: grid-auto-columns,grid-auto-rows
這兩個屬性,主要是用來彌補當元素放的位置超出 grid 時,在外部虛擬生成行/列的大小值。感受有點難懂。。。這個的主要應用場景一樣須要和 item 中的兩個屬性值:grid-column,grid-row 結合使用。這兩個是幹嗎的?他們是根據網格的線來設置元素的位置。
好比:

// 這個 container 只有 2x2 的佈局結構
.container{
  grid-template-columns: 60px 60px;
  grid-template-rows: 90px 90px
}

想這樣:

grid_2x2

如今將一個 item-b 放到 2x5 的右下角位置上。即爲這樣:

grid_2x5

而後設置 grid-column 和 grid-row 能夠爲:

grid-column: 5 / 6;  // 第 5 條到第 6 條豎線之間
grid-row: 2 / 3;  // 第 2 條到第 3 條橫線之間

但這樣的問題是,他雖然確實佔了,可是那個 cell 是 0x0 的,至關於沒有。。。那有啥用。因此,爲了更加靈活的設置, grid 推出的 auto 系列,就有用了。這裏,咱們能夠設置:

grid-auto-columns: 60px;
// 爲啥不設 row? 
// 由於根本就沒超過 row 的範圍。。。

ok,如今就變爲一下的格式:

grid_auto

固然,若是你設置超出了 row 的話,那就適合 grid-auto-rows 便可。如今看一個比較拗口的屬性:

grid-auto-flow

它主要是用來設置多餘元素在剩下位置的排列順序,重置排序。基本格式爲:

// row 爲默認值
grid-auto-flow: row | column | row dense | column dense
  • row:設置剩下的元素按照行順序一次填充,若是超出,自動增長行。

  • column:設置剩下元素按照列順序依次填充,若是超出,自動增長列。

  • dense:強制剩下元素從第一個還未排的 cell 開始。

現假設,咱們有個 3x3 的佈局:
初始樣式爲:

grid_overflow

看一下 CSS:

// 這裏設置的 3x3 佈局。而後將第一個 item 放在第二個 cell 位置
    #container{
        height: 200px;
        display: grid;
        grid-template:repeat(3,1fr) / repeat(3,1fr);
        grid-auto-flow:row;
    }
    .column-1{
        grid-column:2;
        background-color: #F8594C;
    }
    .column-2{
        background-color: #FFA29B;
    }
    //...

而後,剩下的就會依次排開。Ok,如今咱們切換爲 column,他排列方式就變爲:

grid-column-layout

而後咱們再加上 dense 。最後的結果(column dense)就變爲:

grid_column dense

感受,這個屬性仍是挺複雜的,關鍵它的插入算法的機理並無太清楚,並且也還在草案道中,因此,咱們簡單瞭解就好,不深究了。

最後就是 4 個定位佈局的屬性了。

  • justify-items

  • align-items

  • justify-content

  • align-content

items/content

items 相關是用來控制 cell 裏面內容的分佈位置和 flexbox 中的 align-items/justify-content 相似。

justify-items

justify-items 是用來控制 item 水平佈局。基本格式爲:

// stretch 是默認值
justify-items: start | end | center | stretch;

那它的實際效果是啥呢?
看幾張圖,估計就明白了。

justify-items: start;

效果爲:

flex-start

justify-items: center;

效果爲:

flex-center

剩下的 end 和 stretch 我就不贅述了。若是不是 stretch,它都是根據你元素中的文本內容進行自適應寬度的。 在 item 中使用 justify-self 能夠控制獨立 item 的佈局位置。

align-items

align-items 就是用來控制 item 垂直佈局。基本格式爲:

// stretch 是默認值
align-items: start | end | center | stretch;

它的效果和 justify-items 很相似,一樣看幾個 demo:

align-items: start;

效果圖爲:

start

上下的我就很少說了。而且,在 item 中使用 align-self 能夠控制獨立 item 的佈局位置。

剩下的還有兩個:justify-content,align-content

content 相關
它倆作的工做差很少,和上述兩個 tag 最大的區別在於,它們是用來控制整個 container 的佈局。怎麼說呢?
當使用 grid-template-rows/columns 設置行高/列寬時,若是所有使用的都是 px 並無填充滿時,那麼contaienr 就會有一個塊空出來。因此,爲了解決這個問題,grid 就提出了 justify-content,align-content 這兩個 tag。
基本格式爲:

// start 爲默認值
justify-content: start | end | center | stretch | space-around | space-between | space-evenly;    
align-content: start | end | center | stretch | space-around | space-between | space-evenly;

這裏,針對 justify-content 進行下講解,另一個是類似的只是排列方向是按縱向來進行排列的。先假設,咱們經過 grid-template-columns 設置的 container 以下圖:

grid_start

分別添加屬性測試:

justify-content: end;

放後

flex-end

justify-content: center;

放前

grid_center

justify-content: stretch;

拉伸

stretch

justify-content: space-around;

該屬性的意思是,將多餘的 space 均勻分給每個 grid-item(左右都有)。

space-around

space-around

justify-content: space-between;

該屬性的意思是,將多餘的 space 均勻的分在 grid-item 之間,不包括先後。

space-between

space-between

justify-content: space-evenly;

該屬性的意思是,將多餘的 sapce 均勻的分在 grid-item 之間,包括先後。

space-evenly

space-evenly

基本上關於 container 的標籤就已經說完了。下面咱們來看看 items 相關(可少了。。。)

items

items 中的標籤有 3 類:line,area,佈局

line

在 grid 佈局中,定位一個 DOM 的位置,有兩種方式,一種是靠 grid-line,好比,指定你從哪一根開始,另一種是靠 area,好比,將一個 DOM 放在 1,2,3 cell 中。這裏,關於 grid-line 佈局的設置屬性有兩個:行/列

grid-column: grid-column-start / grid-column-end;
grid-row:grid-row-start / grid-row-end;

裏面基本的取值能夠爲:

<number> | <name> | span <number> | span <name> | auto

好比:

grid-column:1/3; // 將 DOM 放在 第一行到第三行之間。
  • number:指定第幾根線,來決定放的位置。

  • name:根據 grid-template-columns 中命名的 grid-line-name 來決定放的位置。

  • span <number>/<name>:至關於到...爲止。一般結合 number 時,效果才能體現出來,好比:1/span 2。表示從第 1 根開始,到過 2 根線位置。最後就是 1/3

好比:

grid-column:1 / col4-start;
grid-row: 2/span 2;

grid-column

area

經過 area 佈局的標籤就一個:grid-area
基本格式爲:

grid-area: <name> | <row-start> / <column-start> / <row-end> / <column-end>;
  • name:根據 grid-template-areas 設置的 cell 的別名。好比:header,foooter 等。

  • row-start/.../column-end: 和上面的 grid-column 一致。用線來框出具體的範圍。

例如:

grid-area: header;
// 或者爲:
grid-area: 1 / col4-start / last-line / 6

佈局

在 container 中提到過,使用 justify-self,align-self 便可實如今 cell 中,content 的排列位置。經常使用取值爲:

justify-self: start | end | center | stretch;
align-self: start | end | center | stretch;

具體的實現方式在 container 中我已經說過了,這裏就不贅述了。

相關文章
相關標籤/搜索