Skip to content

CSS Grid 是一种强大的布局系统,可以用于创建复杂的网页布局。它比 flexbox 更强大,适用于二维(行和列)布局,而 flexbox 主要用于一维布局(行或列)。

基本概念

网格是由一系列水平及垂直的线构成的一种布局模式。根据网格,我们能够将设计元素进行排列,帮助我们设计一系列具有固定位置以及宽度的元素的页面,使我们的网站页面更加统一。

一个网格通常具有许多的列(column)行(row),以及行与行、列与列之间的间隙,这个间隙一般被称为沟槽(gutter)

在 CSS Grid 中,主要涉及以下概念:

  • Grid 容器(Grid Container):使用 display: grid;display: inline-grid; 声明的元素。
  • Grid 项目(Grid Items):直接属于 Grid 容器的子元素。
  • Grid 轨道(Grid Tracks):由列(Columns)和行(Rows)组成的空间。
  • Grid 线(Grid Lines):划分 Grid 轨道的线。
  • Grid 单元格(Grid Cells):网格的最小单位,一个网格行和一个网格列的交叉部分。
  • Grid 区域(Grid Areas):多个 Grid 单元格组成的区域。

创建 Grid 容器

要创建 Grid 布局,需要给一个元素设置 display: grid;

css
.container {
    display: grid;
}

与弹性盒子不同的是,在定义网格后,网页并不会马上发生变化。因为 display: grid 的声明只创建了一个只有一列的网格,所以子项还是会像正常布局流那样,自上而下、一个接一个的排布。

为了让我们的容器看起来更像一个网格,我们要给刚定义的网格加一些列。那就让我们加三个宽度为200px的列。当然,这里可以用任何长度单位,包括百分比。

css
.container {
  display: grid;
  grid-template-columns: 200px 200px 200px;
}

定义列和行

使用 grid-template-columnsgrid-template-rows 来定义网格的列和行。

css
.container {
    display: grid;
    grid-template-columns: 100px 200px auto; /* 第一列 100px,第二列 200px,第三列自动填充 */
    grid-template-rows: 150px auto 100px;   /* 第一行 150px,第二行自动填充,第三行 100px */
}

fr 单位

fr 表示网格的可用空间的比例,通常用于创建弹性布局。

css
.container {
    display: grid;
    grid-template-columns: 1fr 2fr 1fr; /* 3列:第一列占1份,第二列占2份,第三列占1份 */
}

>[!tip] 备注:  >fr单位分配的是_可用_空间而非_所有_空间,所以如果某一格包含的内容变多了,那么整个可用空间就会减少,可用空间是不包括那些已经确定被占用的空间的。

repeat重复构建轨道

你可以使用repeat来重复构建具有某些宽度配置的某些列。举个例子,如果要创建多个等宽轨道,可以用下面的方法。

css
.container {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-gap: 20px;
}

minmax()函数

100 像素高的轨道有时可能会不够用,因为时常会有比 100 像素高的内容加进去。所以,我们可以将其设定为至少 100 像素,并且能够跟随内容来自动拓展尺寸,从而保证能容纳所有内容。显而易见,你很难知道网页上某个元素的尺寸在不同情况下会变成多少,一些额外的内容或者更大的字号就会导致许多能做到像素级精准的设计出现问题。所以,我们有了minmax()函数。

minmax() 函数为一个行/列的尺寸设置了取值范围。比如设定为 minmax(100px, auto),那么尺寸就至少为 100 像素,并且如果内容尺寸大于 100 像素则会根据内容自动调整。在这里试一下把 grid-auto-rows 属性设置为minmax函数。

css
.container {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-auto-rows: minmax(100px, auto);
  grid-gap: 20px;
}

如果所有网格内的内容均小于 100 像素,看起来不会有变化。但如果在某一项中放入很长的内容或者图片,你可以看到这个格子所在的哪一行的高度变成能刚好容纳内容的高度了。注意我们修改的是 grid-auto-rows,因此只会作用于隐式网格。当然,这一项属性也可以应用于显式网格,更多内容可以参考 minmax() 页面。

自动使用多列填充

现在来试试把学到的关于网格的一切,包括 repeat 与 minmax 函数,组合起来,来实现一个非常有用的功能。某些情况下,我们需要让网格自动创建很多列来填满整个容器。通过设置grid-template-columns属性,我们可以实现这个效果,不过这一次我们会用到 repeat() 函数中的一个关键字auto-fill来替代确定的重复次数。而函数的第二个参数,我们使用minmax()函数来设定一个行/列的最小值,以及最大值 1fr

css
.container {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
  grid-auto-rows: minmax(100px, auto);
  grid-gap: 20px;
}

网格间距(gap)

gap 允许设置网格单元之间的间距 - grid-column-gap 属性来定义列间隙

间隙距离可以用任何长度单位包括百分比来表示,但不能使用fr单位。

css
.container {
    display: grid;
    grid-template-columns: 2fr 1fr 1fr;
    grid-template-rows: repeat(2, 100px);
    gap: 10px; /* 行和列间隙 */
}

定位 Grid 项目

通过 grid-columngrid-row 指定位置

css
.item {
    grid-column: 1 / 3; /* 从第1列开始,跨2列 */
    grid-row: 1 / 2;   /* 从第1行开始,跨1行 */
}

也可以使用 span 关键字:

css
.item {
    grid-column: span 2; /* 占据2列 */
}

命名 Grid 区域

另一种往网格放元素的方式是用grid-template-areas属性,并且你要命名一些元素并在属性中使用这些名字作为一个区域

可以通过 grid-template-areas 命名布局区域,使布局更直观。

css
.container {
    display: grid;
    grid-template-areas:
        "header header"
        "sidebar content"
        "footer footer";
    grid-template-columns: 200px auto;
    grid-template-rows: 50px auto 50px;
}

.header { grid-area: header; }
.sidebar { grid-area: sidebar; }
.content { grid-area: content; }
.footer { grid-area: footer; }

grid-template-areas属性的使用规则如下:

  • 你需要填满网格的每个格子
  • 对于某个横跨多个格子的元素,重复写上那个元素grid-area属性定义的区域名字
  • 所有名字只能出现在一个连续的区域,不能在不同的位置出现
  • 一个连续的区域必须是一个矩形
  • 使用.符号,让一个格子留空

自动布局(auto-fit 和 auto-fill)

使用 repeat(auto-fit, minmax(100px, 1fr)) 让网格自动填充空间:

css
.container {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(100px, 1fr));
}
  • auto-fit:填充尽可能多的列,并调整列宽。
  • auto-fill:创建尽可能多的列,但不会扩展已有列。

对齐方式(Alignment)

justify-content(水平对齐)

  • start:对齐到网格起始位置
  • center:居中对齐
  • end:对齐到网格结束位置
  • space-between:均匀排列,两端贴齐
  • space-around:均匀排列,包含两端间距
css
.container {
    justify-content: center;
}

align-content(垂直对齐)

类似 justify-content,但用于控制行的对齐。

css
.container {
    align-content: space-between;
}

justify-itemsalign-items

用于控制网格子项如何对齐:

css
.container {
    justify-items: center;
    align-items: center;
}

place-items

place-itemsalign-itemsjustify-items 的缩写:

css
.container {
    place-items: center center;
}

嵌套 Grid

可以在 grid-item 内部再使用 display: grid; 创建嵌套网格:

css
.parent {
    display: grid;
    grid-template-columns: 1fr 2fr;
}

.child {
    display: grid;
    grid-template-rows: repeat(2, 100px);
}

响应式设计

使用 minmax()auto-fit 让 Grid 自动适应不同屏幕尺寸:

css
.container {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
}

配合 media queries

css
@media (max-width: 600px) {
    .container {
        grid-template-columns: 1fr; /* 仅1列 */
    }
}

评论区

欢迎留言、补充或勘误。

xiaoba.blog