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阅读 204,684评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,143评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,214评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,788评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,796评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,665评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,027评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,679评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,346评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,664评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,766评论 1 331
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,412评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,015评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,974评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,073评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,501评论 2 343