css grid 布局 詳解+代碼示例

本文基于阮一峰大神的文章 http://www.ruanyifeng.com/blog/2019/03/grid-layout-tutorial.html

真誠建議大家去原文看,這篇文是我自己根據阮一峰的文章提煉要點,類似于自己的筆記和感悟。

下面開始正題:

grid 中文意思是網格,所以我們可以想象出,它大概是下面這個樣子:

grid.jpg

每一個方塊可以調,每一根線可以調,方塊與方塊的間距也可以調。

(下面所有的示例,我先給一個完整代碼,剩下的就簡化了,方便大家查看)

一、方塊大小如何調?

方塊的大小說到點子上,也就是方塊的widthheight 。調節widthheight ,基本就三種方式:

  • 絕對值,如 100px,10rem,10vh,10vw等。
  • 百分比,如 50%
  • 絕對值+百分比,如 calc(42% - 0.5rem) 等。(推薦大家去看看 calc,很好用哦~)

(如果還有其他方式,歡迎大家評論中雅正)

1. 在父元素上操作

1.1 首先,父元素要聲明自己是個grid布局的元素(塊級或行內級):

  • 塊級
.container{
  display: grid; /* 一個塊級的grid布局元素,展示效果為另起一行 */
}

效果圖如下:

塊級grid
  • 行內級
.container{
  display: inline-grid; /* 一個行內的grid布局元素,展示效果為與其他行內元素在一行*/
}

效果圖如下:

image.png

1.2 聲明完grid之后,要操作行和列

  • grid-template-columns 控制每一列的寬度
  • grid-template-rows 控制每一行的高度
    這兩個屬性的屬性值可以有多種方式,下面我會一一舉例
1.2.1 絕對值

比如 100px 10rem等具體的值。如下代碼:
一個三列兩行的網格,這個很好理解,大家仔細看代碼

<!DOCTYPE html>
<html lang="zh">
<head>
    <meta charset="UTF-8">
    <style>
        .container{
            color: #fff;
            text-align: center;
            display: grid;
            grid-template-columns: 100px 200px 100px;  /* 三列 */
            grid-template-rows: 200px 100px;  /* 兩行 */
        }
        .item:nth-child(1){background: #00aa00;}
        .item:nth-child(2){background: #0000ff;}
        .item:nth-child(3){background: #ff5500;}
        .item:nth-child(4){background: #ff00ff;}
        .item:nth-child(5){background: #aa0000;}
        .item:nth-child(6){background: #55007f;}
    </style>
</head>
<body>
    <div class="container">
        <div class="item">1</div>
        <div class="item">2</div>
        <div class="item">3</div>
        <div class="item">4</div>
        <div class="item">5</div>
        <div class="item">6</div>
    </div>
</body>
</html>

效果圖如下:


絕對值
1.2.2 百分比

注意,如果行的控制上也用百分比的話,grid元素要先設置height

height:300px;
grid-template-columns: 20% 50% 30%;  /* 三列 */
grid-template-rows: 30% 70%; /* 兩行 */ 

效果圖如下:

百分比
1.2.3 大招:一些神奇的屬性值
1.2.3.1 repeat()

看這個屬性設定

grid-template-columns: 100px 100px 100px; /* 三列 */

上面列數小,只有3列,所以可以枚舉出來。但如果列數大了呢?比如12列,我們也枚舉出來?是不是有點傻?
repeat() 就可以解決這個問題

repeat()接受兩個參數,第一個參數是重復的次數(上例是3),第二個參數是所要重復的值

所以可以寫成

grid-template-columns: repeat(3,100px); /* 絕對值 */
grid-template-columns: repeat(3,33.33%); /* 百分比 */
grid-template-columns: repeat(3,20px 50px 30px); /* 重復三遍模式,一共9列 */
1.2.3.2 auto-fill

有時候,里面的小格子大小固定,但外面的大容器大小不固定,想要小格子盡可能填充滿大容器的每一行或每一列,這時可以用到auto-fill
先看充滿一行:

grid-template-columns: repeat(auto-fill, 130px);    /* 盡可能充滿一行 */

效果圖:

盡可能充滿一行

充滿一列

height: 500px;
grid-auto-flow: column; /* 先確定按列排 */
grid-template-rows: repeat(auto-fill, 120px);

效果圖:

盡可能充滿一列
1.2.3.3 fr

網格布局提供了fr關鍵字(fraction 的縮寫,意為"片段")。如果兩列的寬度分別為1fr和2fr,就表示后者是前者的兩倍。

個人認為單純使用fr來表示比例沒有任何意義,和百分比效果一樣,頂多是寫法上更方便一些,因為不用計算百分比。fr和絕對值配合使用,才會發揮出巨大的作用

比如說,現在有這么個需求:一個div,寬度隨屏幕自適應,里面有三個元素排成一行,第一個元素100px的寬度,第三個元素寬度是第二個的二倍,要求三個元素充滿整個div。我們就可以使用fr來實現。

  grid-template-columns: 100px 1fr 2fr;

效果圖如下:

fr
1.2.3.4 minmax()

設置最小最大的范圍。

grid-template-columns: 100px 100px minmax(120px ,1fr);
1.2.3.5 auto

經常適用于以下場景:
一個div,寬度隨屏幕自適應,里面三個元素排成一行,第一個和第三個各100px,第二個充滿剩余空間

grid-template-columns: 100px auto 100px;

效果圖如下:

auto

二、網格線

1. 指定網格線名稱

grid-template-columns屬性和grid-template-rows屬性里面,還可以使用方括號,指定每一根網格線的名字,方便以后的引用

grid-template-columns: [cl1] 100px [cl2] auto [cl3] 100px [cl4];
grid-template-rows: [rl1] 100px [2l2] auto [rl3];

三、方塊與方塊的間距

  • 設置列間距 column-gap
  • 設置行間距 row-gap
  • gap: <row-gap> <column-gap>; 前兩者簡寫形式
grid-template-columns: [cl1] 100px [cl2] auto [cl3] 100px [cl4];
grid-template-rows: [rl1] 100px [2l2] auto [rl3];
column-gap: 10px;
row-gap: 20px;

效果圖:

image.png

四、布局相關

1. grid-template-areas

grid布局會分出很多小單元格,這個屬性就可以給單元格命名,方便引用

display: grid;
grid-template-columns: 100px 100px 100px;
grid-template-rows: 100px 100px 100px;
grid-template-areas: 'a b c'
                     'd e f'
                     'g h i';

如上代碼,九個單元格按照位置命名了。
如果有些單元格,我們不需要引用,那么就不需要命名,該相對位置就用.代替:

grid-template-areas: 'a . c'
                     'd e .'
                     'g . i';

2. grid-auto-flow

默認排列單元格的方式

  • 按行排: grid-auto-flow: row;
  • 按列排: grid-auto-flow: column;

像不像flex布局里的 flex-direction

grid-auto-flow: column;
grid-template-columns:  50px  auto  50px ;
grid-template-rows:  50px  auto ;

效果圖如下(仔細體會行和列哦,并沒有改變,只是排列方式變了):

按列排序

** 有一個 dense ** 的東西,指定某個單元格放在確定位置,其他的如何擺放,說實話我覺得用處不大,先不寫了

3. justify-items、align-items 、place-items

  • justify-items:單元格內容的水平位置
    主要有四個值:stretch | start | end | center。
    stretch是默認值,拉伸,占滿整個單元格位置。
    給大家看一個start的完整代碼。
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>JS Bin</title>
    <style type="text/css">
        #container{
            display: grid;
            grid-template-columns: 100px 100px 100px;
            grid-template-rows: 100px 100px 100px;
            justify-items: start;   /* start 布局 */
        }
        .item {
            font-size: 2em;
            text-align: center;
            border: 1px solid #000;
        }
        .item-1 {background-color: #ef342a;}
        .item-2 {background-color: #f68f26;}
        .item-3 {background-color: #4ba946;}
        .item-4 {background-color: #0376c2;}
        .item-5 {background-color: #c077af;}
        .item-6 {background-color: #f8d29d;}
        .item-7 {background-color: #b5a87f;}
        .item-8 {background-color: #d0e4a9;}
        .item-9 {background-color: #4dc7ec;}
    </style>
</head>
<body>
    <div id="container">
        <div class="item item-1">1</div>
        <div class="item item-2">2</div>
        <div class="item item-3">3</div>
        <div class="item item-4">4</div>
        <div class="item item-5">5</div>
        <div class="item item-6">6</div>
        <div class="item item-7">7</div>
        <div class="item item-8">8</div>
        <div class="item item-9">9</div>
    </div>
</body>
</html>

效果圖:

start
  • align-items:單元格內容的垂直位置,與上面的justify-items 同理。
  • place-items:前面兩者的合稱

4. justify-content、align-content、place-content

  • justify-content: 內容區域(那些聚在一起的單元格)在整個容器內水平方向的布局
    取值:start | end | center | stretch | space-around | space-between | space-evenly;
    start是默認值。
    舉一個center的例子,下面是完整代碼:
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>JS Bin</title>
    <style type="text/css">
        #container{
            display: grid;
            width: 500px;
            height: 500px;
            border: 1px solid #000000;
            grid-template-columns: 100px 100px 100px;
            grid-template-rows: 100px 100px 100px;
            justify-content: center;
        }
        .item-1 {background-color: #ef342a;}
        .item-2 {background-color: #f68f26;}
        .item-3 {background-color: #4ba946;}
        .item-4 {background-color: #0376c2;}
        .item-5 {background-color: #c077af;}
        .item-6 {background-color: #f8d29d;}
        .item-7 {background-color: #b5a87f;}
        .item-8 {background-color: #d0e4a9;}
        .item-9 {background-color: #4dc7ec;}
    </style>
</head>
<body>
    <div id="container">
        <div class="item item-1">1</div>
        <div class="item item-2">2</div>
        <div class="item item-3">3</div>
        <div class="item item-4">4</div>
        <div class="item item-5">5</div>
        <div class="item item-6">6</div>
        <div class="item item-7">7</div>
        <div class="item item-8">8</div>
        <div class="item item-9">9</div>
    </div>
</body>
</html>

效果圖:

center
  • align-content : 內容區域(那些聚在一起的單元格)在整個容器內水平方向的布局
  • place-content屬性是align-content屬性和justify-content屬性的合并簡寫形式。

5. grid-auto-columns、grid-auto-rows

比如網格只有3列,但是某一個項目指定在第5行。這時,瀏覽器會自動生成多余的網格,以便放置項目。
一個代碼示例:

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>JS Bin</title>
    <style type="text/css">
        #container{
            display: grid;
            width: 500px;
            height: 500px;
            border: 1px solid #000000;
            grid-template-columns: 100px 100px 100px;
            grid-template-rows: 100px 100px 100px;
        }
        
        .item-1 {background-color: #ef342a;}
        .item-2 {background-color: #f68f26;}
        .item-3 {background-color: #4ba946;}
        .item-4 {background-color: #0376c2;}
        .item-5 {background-color: #c077af;}
        .item-6 {background-color: #f8d29d;}
        .item-7 {background-color: #b5a87f;}
        .item-8 {background-color: #d0e4a9;}
        .item-9 {background-color: #4dc7ec;}
        
        .item-1{
            grid-row-start: 4;
            grid-row-start: 5;
        }
    </style>
</head>
<body>
    <div id="container">
        <div class="item item-1">1</div>
        <div class="item item-2">2</div>
        <div class="item item-3">3</div>
        <div class="item item-4">4</div>
        <div class="item item-5">5</div>
        <div class="item item-6">6</div>
        <div class="item item-7">7</div>
        <div class="item item-8">8</div>
        <div class="item item-9">9</div>
    </div>
</body>
</html>

效果圖:

auto

6. grid-column-start、grid-column-end、grid-row-start、grid-row-end

指定某一項目的四個邊框,從而指定某一項目的具體位置,如下代碼:

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>JS Bin</title>
    <style type="text/css">
        #container{
            display: grid;
            grid-template-columns: 100px 100px 100px ;
            grid-template-rows: 100px 100px 100px ;
        }
        
        .item-1 {background-color: #ef342a;}
        .item-2 {background-color: #f68f26;}
        .item-3 {background-color: #4ba946;}
        .item-4 {background-color: #0376c2;}
        .item-5 {background-color: #c077af;}
        .item-6 {background-color: #f8d29d;}
        .item-7 {background-color: #b5a87f;}
        .item-8 {background-color: #d0e4a9;}
        .item-9 {background-color: #4dc7ec;}
        
        .item-1{
            /* 指定位置 */
            grid-row-start: 2;
            grid-row-end: 3;
            grid-column-start: 2;
            grid-column-end: 3;
        }
    </style>
</head>
<body>
    <div id="container">
        <div class="item item-1">1</div>
        <div class="item item-2">2</div>
        <div class="item item-3">3</div>
        <div class="item item-4">4</div>
        <div class="item item-5">5</div>
        <div class="item item-6">6</div>
        <div class="item item-7">7</div>
        <div class="item item-8">8</div>
        <div class="item item-9">9</div>
    </div>
</body>
</html>

效果圖:

設置位置

7. grid-area

指定項目放在哪一個區域,主要有兩種方法

7.1 直接指定區域

#container{
    display: grid;
    grid-template-columns: 100px 100px 100px ;
    grid-template-rows: 100px 100px 100px ;
    grid-template-areas: 'a b c'
                         'd e f'
                         'g h i';
}
        
.item-1{
    grid-area: f;   /* 直接指定 */
}

7.2 通過線來指定區域

#container{
    display: grid;
    grid-template-columns: 100px 100px 100px ;
    grid-template-rows: 100px 100px 100px ;
}       
.item-1{
    grid-area: 2/3/3/4;
}

8. justify-self、align-self、place-self

設置單元格內容的水平或垂直位置,只作用于單個項目
太簡單了。。。跟上面justify-items一樣的原理。

到這兒就算完了,太不容易了,好懵。。。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。