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一樣的原理。

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

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