现代 CSS

图解CSS: Grid布局(Part2)

特别声明:如果您喜欢小站的内容,可以点击申请会员进行全站阅读。如果您对付费阅读有任何建议或想法,欢迎发送邮件至: airenliao@gmail.com!或添加QQ:874472854(^_^)

在上一节中,主要介绍了 CSS 网格布局中的一些重要概念和相关术语。从这些概念和术语中,从侧面也再次说明CSS 网格布局到目前为止是最为复杂的一个布局系统,换句话说,CSS 网格布局系统中会有很多属性,这些属性和 Flexbox 布局有些类似,有些属性只能作用于网格容器,有些属性只能作用于网格项目。而在这篇文章中,先从可用于网格容器的属性,即使用display属性创建网格容器和网格项目, grid-template-areasgrid-template-columnsgrid-template-rows 以及这三个属性的简写属性grid-template 来定义显式网格。如果感兴趣的请继续往下阅读。

网格布局中的属性

CSS 网格布局中涉及到的属性和 Flexbox 布局类似,可分为两个部分,其中一部分可用于 网格容器 的属性;另一部分是可用于 网格项目 的属性。接下来我们来看看这些属性的使用和所起的作用。

可用于网格容器的属性

到目前为止,CSS 网格布局模块 Level 1Level 2Level 3 几个不同版本规范的定义的可以用于网格容器的属性主要有:

在这些属性列表中,有些属性到现在还未得到浏览器的支持,或者仅得到个别主流浏览器的支持,比如前面提到的 subgrid 属性,而且有些还仅是实验性的属性,比如 Level 3 中的 masonry-auto-flow。这里要特别提出的是 CSS 网格布局模块 Level 3 ,目前还是处于规范的 ED 阶段,里面所提到的部分属性还处于不确定状态,有可能会随着后面的规范完善程度随之改变,因此,我们在这里不会在 Level 3 规范中提到属性花多少时间。

创建网格容器和网格项目 display

创建网格容器和网格项目很简单,只需要在容器上显式设置 display 的值为 gridinline-grid,该容器就成为网格容器,其子元素以及文本节点,伪元素就成为网格项目。

  • griddisplay 取值为 grid 时会使一个元素产生一个网格容器,当放在流式布局中时,它是块状的,称之为块网格容器
  • inline-griddisplay 取值为 inline-grid 时会使一个元素产生一个网格容器,当放在流式布局中时,它是内联的,称之为内联的网格容器

一个网格容器为其内容建立了一个独立的网格格式化上下文(Grid Formatting Content,即 GFC)。这与建立一个独立的块格式化上下文(Block Formatting Content,即 BFC)是一样的,只是使用了网格布局而不是块布局。网格容器的内容被布置成一个网格,网格线形成了每个网格项目所含块的边界。

网格容器不是块状容器,因此一些块状布局而设计的属性在网格布局中并不适用。特别是:

  • floatclear 对网格项目没有影响。然而, float 属性仍然会影响到网格容器的子项上的 display 的计算值,因为这发生在网格项被确定之前
  • vertical-align 对一个网格项没有影响
  • ::first-line::first-letter 伪元素不适用于网格容器,而且网格容器不会为其祖先提供第个格式化的行或第一个字母

如果一个元素指定 display 的值是 inline-grid,并且该元素是浮动的或绝对定位的,那么该元素的 display 的计算值是 grid

虽然在一个元素上显式设置 display 的值为 gridinline-grid 值,但你看到的效果和 display 值为 blockinline 相似的效果,比如下面这个示例:

<!-- HTML -->
<div class="grid__container">
    <div class="grid__item">Grid Item</div>
    Anonymous Item
    <div class="grid__item" style="float: left">Float Element</div>
</div>
<span>Inline Element</span>

/* CSS */
.grid__container {
    --display: grid;
    display: var(--display);
}

这是因为没有在网格容器上显式创建任何行或列,但事实上此时创建的是一个真实的网格容器,只不过这个时候网格是一个单列网格,网格的行由网格容器的子元素所决定,并且它们在单列中一个接一个地显示。从视觉上看,它们就像块状元素。

你可能已经看到了,示例中的“Anonymous Item” 是一个文本节点,并没有包裹在一个元素中,但它属于网格容器的子元素,它也成为一个网格项。网格容器的伪元素,比如示例中的 ::before::after 也将成为网格项目。

示例中 grid 切换到 inline-grid 时,网格容器变成一个内联级的盒子(内联网格容器),然而,其直接的子元素仍然是网格项目,其表现行为与块容器中的网格项目相同。

另外,在示例中的容网格容器 div.grid__container 下面有一个 span元素放置了一串文字,当 display 的值为 grid 时,该网格容器是个块级网格容器,其表现形为类似于块级元素,所以 span 元素会在另一行开始排列;当 grid 切换到 inline-grid 时,该网格容器就变成了一个内联级网格容器,所以 span 元素可以在它的旁边显式。

注意,你可能在某些介绍 CSS 网格布局的相关教程中有看到 display 取值 subgrid。这里要告诉大家的是,在写这篇文章的时候,subgrid 值已从 display 属性值列表中删除。

在 CSS 中创建网格容器是使用 display 的值来创建的,有关于 display 更深入的介绍,可以阅读《Web布局:display 属性》一文。

网格容器的尺寸

网格容器的尺寸是使用它所参与的格式化上下文的规则来确定的:

  • 作为一个块格式化上下文中的块级框,它的尺寸与建立格式化上下文的块级框一样,与非替换的块级框一样计算自动内联尺寸
  • 作为一个内联格式化上下文中的内联级框,它的尺寸与原子内联级框(内联块)一样

在内联和块格式化上下文中,网格容器的自动块尺寸是其最大内容(max-content)的大小。

一个网格容器的最大内容尺寸(max-content)或最小内容尺寸(min-content)是该网格容器在适当的轴上的轨道尺寸(包括网格沟槽)的总和。

简单地来说,网格容器的尺寸可以像其它元素容器一样,使用尺寸相关的属性(比如 widthmax-widthmin-widthheightmax-heightmin-height与及其对应的逻辑属性)来设置。比如下面这个示例:

.grid__container {
    --grid: grid;
    --width: 40;
    --height: 30;
    display: var(--grid);
    grid-template-columns: repeat(3, 200px);
    gap: 10px;
    width: calc(var(--width) * 1vw);
    height: calc(var(--height) * 1vh);
    overflow: auto;
}

就该示例而言,我们在网格容器上显式设置了 widthheight(拖动滑块可以动态调整它们的值),同时使用 grid-template-columns 指定了每列列宽是 200px,每行行高根据网格项目自身高度尺寸来决定。这样一来,在拖动滑块时,网格容器的 width 值有可能小于三列加沟槽的总和(此例是 320px),也有可能大于它们的总和:

  • width 小于 320px 时,网格容器会出现水平滚动条(因为容器显式设置了overflow: auto
  • width 大于 320px 时,网格容器会有空白空间留出

网格容器的高度和宽度类似的,只不过没有显式使用 grid-template-rows 来显式指每行的行高,而是由网格项目盒模型自身决定。你将看到的效果如下:

除此之外,我们还可以通过 grid-template-columnsgrid-template-rows 以及 gap 等属性来控制网格容器的尺寸:

.grid__container {
    --col-1: 100;
    --col-2: 100;
    --col-3: 100;
    --row-1: 50;
    --row-2: 50;
    --row-3: 50;
    display: grid;
    grid-template-columns:
        calc(var(--col-1) * 1px)
        calc(var(--col-2) * 1px)
        calc(var(--col-3) * 1px);
    grid-template-rows:
        calc(var(--row-1) * 1px)
        calc(var(--row-2) * 1px)
        calc(var(--row-3) * 1px);
    gap: 10px;
}

拖动示例中的滑块,可以看到网格容器尺寸的变化:

网格项目的尺寸

在网格布局中,除了 grid-template-columnsgrid-template-rowsgrid-template-areas 以及 grid-columngrid-rowgrid-area 等属性可以决定网格项目尺寸之外,还有我们熟悉的设置元素尺寸的相关属性,比如《图解CSS: 元素尺寸的设置》一文中提到的 widthheight 等属性。

除此之外,网格项目的尺寸还会受设置在网格项目上的对齐属性,比如 align-selfjustify-self的影响。有关于这方面的更详细的介绍,我们放到后面介绍网格中的对齐方式一节中来介绍。

定义网格

元素显式设置 display 的值为 gridinline-grid 只是帮助我们创建了一个网格容器(格式化上下文而以)。但定义一个网格还是需要依赖于其他的一些属性,比如前面示例中多次出现的 grid-template-columnsgrid-template-rowsgrid-template-areas,还有 grid-auto-rowsgrid-auto-columns等属性。根据不同的属性,我们定义的网格又分为 显式网格隐式网格 。其中 grid-template-columnsgrid-template-rowsgrid-template-areas 三个属性定义的网格被称为 显式网格grid-auto-rowsgrid-auto-columns 定义的网格被称为 隐式网格

定义显式网格:grid-template-columns/rows/areas

在 CSS 网格布局,如果在网格容器中显式使用了 grid-template-columnsgrid-template-rowsgrid-template-areas 三个属性指定了网格轨道,那么这个网格就被称为 显式网格

grid-template-rowsgrid-template-columns

先来看 grid-template-rowsgrid-template-columns

我们可以在 grid-template-rowsgrid-template-colums 属性上设置用空格分隔开来的多个数值,这些数值列表定义了网格的行和列。这些值同时代表网格轨道的大小,它们之间的空格代表网格线。这两个属性可接受的值:

grid-template-columns: none | <track-list> | <auto-track-list>
grid-template-rows: none | <track-list> | <auto-track-list>

其中 none 是其初始值,表示此属性不创建显式网格轨道(尽管显式网格轨道仍可由 grid-template-areas 创建)。

注意,在没有显式网格的情况下,任何行和列都将被式生成,它们的大小将由 grid-auto-rows

剩余80%内容付费后可查看
返回顶部