grid布局详解

1. 基本网格

1.1 为了演示后续效果,先书写一个基本结构

<!DOCTYPE html>
<html lang="zh-CN">
    <head>
        <meta charset="utf-8">
        <title>grid布局</title>
        <style>
            .wrapper {
                width: 750px;
                height: 348px;
                border: 4px solid #1E7F9D;
                padding: 30px;
                box-sizing: border-box;
            }
            .wrapper > div {
                background-color: #CFE8DC;
                border-radius: 10px;
            }
        </style>
    </head>
    <body>
        <div class="wrapper">
            <div class="box1">One</div>
            <div class="box2">Two</div>
            <div class="box3">Three</div>
            <div class="box4">Four</div>
            <div class="box5">Five</div>
        </div>
    </body>
</html>
复制代码

image.png

1.2 grid-template-columns

用于控制一行中显示多少列,以及每列所占的宽度比例,推荐使用fr单位,其表示按照比例分配所剩的空间

.wrapper {
    width: 750px;
    height: 348px;
    border: 4px solid #1E7F9D;
    padding: 30px;
    box-sizing: border-box;
    
    display: grid;
    grid-template-columns: 1fr 1fr 1fr;
}
复制代码

可以看到我们使用了3个1fr,表示将一行等比分成3列,像这种等比划分,重复书写,我们可以简写为以下的方式

.wrapper {
    width: 750px;
    height: 348px;
    border: 4px solid #1E7F9D;
    padding: 30px;
    box-sizing: border-box;
    
    display: grid;
    grid-template-columns: repeat(3,1fr);
}
复制代码

这里使用repeat,参数1表示重复次数,参数2表示距离值 image.png

1.3 grid-template-rows

用于控制每行所占的高度比例,推荐使用fr单位,其表示按照比例分配所剩的空间(需要先通过grid-template-columns将行划分出来后再使用)

需要注意:必须要给盒子设定高度,该样式才会生效哦

.wrapper {
    width: 750px;
    height: 348px;
    border: 4px solid #1E7F9D;
    padding: 30px;
    box-sizing: border-box;
    display: grid;
    grid-template-columns: repeat(3,1fr);
    
    grid-template-rows: 1fr 2fr;
}
复制代码

可以明显看到下图中,第二行的高度是第一行高度的2倍 image.png

1.4 grid-gap与gap

grid-gapgap都是用于设置网格之间的间距(包括行与列),grid-gapgrid标准遗留样式,因此不再推荐使用,推荐使用gap,该属性目前最新的flex也加入了,参考文章:CSS gap属性进化史

.wrapper {
    width: 750px;
    height: 348px;
    border: 4px solid #1E7F9D;
    padding: 30px;
    box-sizing: border-box;
    display: grid;
    grid-template-columns: repeat(3,1fr);
    grid-template-rows: 1fr 2fr;
    
    gap: 10px;
    /* grid-gap: 10px; */
}
复制代码

可以看到下图,每个格子之间出现了10px的间隔 image.png

只控制行的间距或控制列的间距

gap是用于同时控制行和列的间隔,我们也可以使用row-gap控制行之间的间隔以及column-gap控制列之间的间隔,当然grip标准也遗留两个等效的样式grid-row-gapgrid-column-gap

.wrapper {
    width: 750px;
    height: 348px;
    border: 4px solid #1E7F9D;
    padding: 30px;
    box-sizing: border-box;
    display: grid;
    grid-template-columns: repeat(3,1fr);
    grid-template-rows: 1fr 2fr;
    
    row-gap: 10px;
    /* grid-row-gap: 10px; */
}
复制代码

image.png

.wrapper {
    width: 750px;
    height: 348px;
    border: 4px solid #1E7F9D;
    padding: 30px;
    box-sizing: border-box;
    display: grid;
    grid-template-columns: repeat(3,1fr);
    grid-template-rows: 1fr 2fr;
    
    column-gap: 10px;
    /* grid-column-gap: 10px; */
}
复制代码

image.png

1.5 隐式与显式网格

前面我们使用的grid-template-columnsgrid-template-rows即为显式网格,而现在我们可以使用grid-auto-columnsgrid-auto-rows来隐式的控制网格

通常我们将grid-auto-columnsgrid-auto-rows用来统一控制网格的大小

.wrapper {
    width: 750px;
    height: 348px;
    border: 4px solid #1E7F9D;
    padding: 30px;
    box-sizing: border-box;
    display: grid;
    grid-template-columns: repeat(3,1fr);
    gap: 10px;

    grid-auto-rows: 100px;
}
复制代码

image.png

最大或最小函数minmax()

该函数可以传递2个参数,第1个参数用于控制最小值(常用值是:固定像素值),第2个参数用于控制最大值(常用的值是:固定像素值、auto)。需要注意的是,第2个参数即便写了固定值,但是并不是强制值,其内容值会扩展到父级饱和之后结束,可能文字不太明白,看看下面的示例:

第2个参数使用固定值并未达到父级饱和

<!DOCTYPE html>
<html lang="zh-CN">
    <head>
        <meta charset="utf-8">
        <title>grid布局</title>
        <style>
            .wrapper {
                width: 750px;
                height: 348px;
                border: 4px solid #1E7F9D;
                padding: 30px;
                box-sizing: border-box;
                display: grid;
                grid-template-columns: repeat(3,1fr);
                gap: 10px;
                
                grid-auto-rows: minmax(100px,130px);
            }
            .wrapper > div {
                background-color: #CFE8DC;
                border-radius: 10px;
            }
        </style>
    </head>
    <body>
        <div class="wrapper">
            <div class="box1">
                <p>One</p>
                <p>One</p>
                <p>One</p>
                <p>One</p>
                <p>One</p>
            </div>
            <div class="box2">Two</div>
            <div class="box3">Three</div>
            <div class="box4">Four</div>
            <div class="box5">Five</div>
        </div>
    </body>
</html>
复制代码

可以看到,第一个框的内容溢出了,同时,其它网格的高度都变成了130,且此时父级的高度还未完全被占用完(下方还有些许的空白) image.png

第2个参数使用固定值并达到父级饱和

我们将上述代码的130px改为150px

.wrapper {
    width: 750px;
    height: 348px;
    border: 4px solid #1E7F9D;
    padding: 30px;
    box-sizing: border-box;
    display: grid;
    grid-template-columns: repeat(3,1fr);
    gap: 10px;

    grid-auto-rows: minmax(100px,150px);
}
复制代码

我们可以看到,虽然我们设定的是150px,但是当网格的高度到达135px的时候,父级高度高度已经被占用完了,因此网格的高度不会再增加 image.png

第2个参数使用auto

我们将上述代码的150px改为auto

.wrapper {
    width: 750px;
    height: 348px;
    border: 4px solid #1E7F9D;
    padding: 30px;
    box-sizing: border-box;
    display: grid;
    grid-template-columns: repeat(3,1fr);
    gap: 10px;

    grid-auto-rows: minmax(100px,auto);
}
复制代码

可以发现,使用auto之后,同行的网格会尽可能多的占用空白处,而其它行则使用最小值(前提是它的高度没有超出最小值,如果超出,那么自动计算) image.png

image.png

2. 基础行的位置

2.1 为了显示后续效果,先书写一个基本结构

<!DOCTYPE html>
<html lang="zh-CN">
    <head>
        <meta charset="utf-8">
        <title>基于行的位置</title>
        <style>
            header, footer {
                border-radius: 5px;
                padding: 10px;
                background-color: #CFE8DC;
                border: 2px solid #4FB9E3;
            }
        </style>
    </head>
    <body>
        <div class="container">
          <header>This is my lovely blog</header>
          <article>
            <h1>My article</h1>
            <p>Duis felis orci, pulvinar id metus ut, rutrum luctus orci. Cras porttitor imperdiet nunc, at ultricies tellus laoreet sit amet. Sed auctor cursus massa at porta. Integer ligula ipsum, tristique sit amet orci vel, viverra egestas ligula. Curabitur vehicula tellus neque, ac ornare ex malesuada et. In vitae convallis lacus. Aliquam erat volutpat. Suspendisse ac imperdiet turpis. Aenean finibus sollicitudin eros pharetra congue. Duis ornare egestas augue ut luctus. Proin blandit quam nec lacus varius commodo et a urna. Ut id ornare felis, eget fermentum sapien.</p>
            <p>Nam vulputate diam nec tempor bibendum. Donec luctus augue eget malesuada ultrices. Phasellus turpis est, posuere sit amet dapibus ut, facilisis sed est. Nam id risus quis ante semper consectetur eget aliquam lorem. Vivamus tristique elit dolor, sed pretium metus suscipit vel. Mauris ultricies lectus sed lobortis finibus. Vivamus eu urna eget velit cursus viverra quis vestibulum sem. Aliquam tincidunt eget purus in interdum. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.</p>
          </article>
          <aside>
            <h2>Other things</h2>
            <p>Nam vulputate diam nec tempor bibendum. Donec luctus augue eget malesuada ultrices. Phasellus turpis est, posuere sit amet dapibus ut, facilisis sed est.</p>
          </aside>
          <footer>Contact me@mysite.com</footer>
        </div>
    </body>
</html>
复制代码

image.png

2.2 grid-row与grid-column

我们可以使用grid-row来控制网格处于第几行,使用grid-column控制网格的起始位置线与结束位置线(注意这里说的是线,也就是分割线,例如我们要将一行分成两列,那么就是3条线)

现在来看看下面代码:

.container {
  display: grid;
}
header {
  grid-column: 1 / 3;
  grid-row: 1;
}

article {
  grid-column: 2;
  grid-row: 2;
}

aside {
  grid-column: 1;
  grid-row: 2;
}

footer {
  grid-column: 1;
  grid-row: 3;
}
复制代码

我们可以看到,下图中,header因为起始线是1,因此它占满了整行,那后面/ 3的意义是什么呢(看下一个案例);同时我们可以明显看到,网格中的列数是同步的,因此即便我们没有明确写出来,第2行和第3行依然被分成了2列 image.png

一个网格中不同行分割成了不同的列数

尝试将上述案例中的footergrid-column: 1调整为grid-column: 3 / 4会发生什么,看看下图

image.png

我们可以看到footer被分成了4列,而header的长度并未占满整行了

3.grid-template-areas

使用grid-template-areas为每个网格定义名称,之后通过grid-area定义名称,凡是与grid-template-areas名称对应的区域将会显示该网格(需要注意,我们在定义区域的时候,一定要连贯在一起且呈矩形,否则区域划分会出现错误)

3.1 为了演示该效果,我们需要先准备一下以下代码

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>网格内容快速填充</title>
        <style>
            .container {
                background-color: #eee;
                border: .75em solid;
                padding: .75em;
                display: grid;
                grid-template-columns: repeat(3,1fr);
                grid-template-rows: repeat(3,minmax(40px,auto));
                grid-gap: 10px;
                width: 200px;
            }
            .container :nth-child(1) {
                background-color: rgba(0,0,255,.2);
                border: 3px solid #00f;
            }
            .container :nth-child(2) {
                background-color: rgba(255,0,200,.2);
                border: 3px solid #663399;
            }
            .container :nth-child(3) {
                background-color: rgba(94,255,0,.2);
                    border: 3px solid green;
            }
        </style>
    </head>
    <body>
        <div class="container">
            <div>One (a)</div>
            <div>Two (b)</div>
            <div>Three (c)</div>
        </div>
    </body>
</html>
复制代码

image.png

定义网格名称

我们先使用grid-area给3个div分别命名

.container :nth-child(1) {
    background-color: rgba(0,0,255,.2);
    border: 3px solid #00f;
    grid-area: a;
}

.container :nth-child(2) {
    background-color: rgba(255,0,200,.2);
    border: 3px solid #663399;
    grid-area: b;
}

.container :nth-child(3) {
    background-color: rgba(94,255,0,.2);
    border: 3px solid green;
    grid-area: c;
}
复制代码

此时还未定义区域名称,因此所有网格均处于右下角 image.png

定义区域名称

grid-template-areas: 
            'a a b'
            'a a b'
            'c c b';
复制代码

image.png

自行尝试改变区域划分,看看最终结果

分类:
前端
标签: