本文主要内容翻译自 https://css-tricks.com/snippets/css/complete-guide-grid/ 一文的属性那部分,其中间也有我自己的理解和看法。

Grid Container 网格容器相关属性

display

.container{
  display:grid | inline-grid
}

将一个元素变成grid盒子,这个盒子,我们称之为“网格容器”,grid的表现为块状(block)、inline-grid表现为行内(inline)。
此条样式一量加上,那么其里面的所有元素都会变成网格元素(grid item)

grid-template-columns & grid-template-rows

grid-template-columnsgrid-template-rows用来定义网格的行和列,它们的名字当中都有一个template,也就是说有模板这一层意思在,所以在我看来,这两个属性就是用来定义“网格模板”的,把它定义好,里面的网格元素按照它进行排列摆放。
它们的属性值用来定义行/列的大小(track size),在各个属性值中间的空格(空格也可以用任意字符代替,用来给网格线取名字)即代表了一条一条的网格线(line name)

  • track size值 – :一个长度单位 ,用来控制网格元素的大小,可以是一个固定长度,也可以是百分比,或者是用fr单位定义的“长度”,这个长度会根据多余的空间自动进行伸缩(就像flex而局里的flex-grow属性一样)。
  • line name值 – :网格线的名字,可以是任意字符,但需要用方括号括起来,比如[row1-start]

例如:

.container {
  grid-template-columns: [first] 40px [line2] 50px [line3] auto [col4-start] 50px [five] 40px [end];
  grid-template-rows: [row1-start] 25% [row1-end] 100px [third-line] auto [last-line];
}

上面的样式会生成如下网格:

一条网格线也可以取多个名字,比如第一行的结束也是第二行的开始:

.container {
  grid-template-rows: [row1-start] 25% [row1-end row2-start] 25% [row2-end];
}

如果你想定义多组相同的值,那么可以用repeat()来进行循环:

.container {
  grid-template-columns: repeat(3, 20px [col-start]);
}

上面的代码等价于:

.container {
  grid-template-columns: 20px [col-start] 20px [col-start] 20px [col-start];
}

这些网格线的名称将会在网格元素上用到,比如指定元素从名为 col-start 的网格线处开始,并且占两列:

.item {
  grid-column-start: col-start 2;
}

fr单位可以让网格元素按照比例来分配“剩余空间”,比如你想让网格分成三列,每一列都占用相同的地方:

.container {
  grid-template-columns: 1fr 1fr 1fr;
}

“剩余空间”是根据所有“非弹性”元素计算得来的,比如下面,在所有的“剩余空间”都会被设置了fr单位的元素占用,但是设置了50px的元素跟这些“剩余空间”就没有一点的关系。

.container {
  grid-template-columns: 1fr 50px 1fr 1fr;
}

grid-template-areas

通过 grid-template-area 属性可以给网格区域进行命名,以后网格元素可以通过grid-area属性来根据这些名字来进行引用布局。如果在多个“单元格”里使用相同的名称,那么说明这些单格将会被合并,以后你通过这个名称来设置网格元素的时候会尽量把这个区域撑满。如果名称是一个句号(英文句号,即一个点).,则代表这是一个空的单元格。grid-template-areas值的语法本身看起来就是可以写成一个可视化的网格的。

  • <grid-area-name> – 网格区域名称
  • . – 网格区域为空
  • none – 该位置没有定义网格区域
.container {
  grid-template-areas: 
    "<grid-area-name> | . | none | ..."
    "...";
}

利用网格区域命名来举个例子:

.item-a {
  grid-area: header;
}
.item-b {
  grid-area: main;
}
.item-c {
  grid-area: sidebar;
}
.item-d {
  grid-area: footer;
}

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

上面定义了一个4列3行的网格模板,最上面的一行区域被取名为 header,它会被.item-a元素完全占据。中间一行左边两格取名为main,它会被.item-b元素占据,随后空了一格,中间最右是sidebar,被.item-c占据。最后一行则是被 .item-d占据,也就是footer

每一行的名称定义都必须得和你grid-template-columns定义的单元格数相同,也就是上面说的可视话的属性值语法。

上面说到你可以用一个英文句号.来表示一个空的格子,其实你可以使用任何数量的点来进行表示空格子,只要它们是连续的,中间没有穿的。

需要注意的是,我们并没有通过上面的方法来命名“网格线”,只是网格区域。但事实上,当我们给网格区域进行命名之后,这个网格系统当中的网格线会被自动命名。如果网格区域的名字是foo,那么foo区域周围的线就会自动命名为foo-startfoo-end,即在区域前面横向和纵向的线叫foo-start。相反,在其后面的线叫做foo-end。这就意味着,有一些网格线会有多个名称,就比如上面例子当中最左边的网格线,它会有三个名字:header-startmain-start,footer-start

grid-template

此属性是grid-template-rows,grid-template-columns,grid-template-areas三个属性的缩写形式。

值格式为:
none – 把它们三个属性全都设置成初始状态。
<grid-template-rows> / <grid-template-columns> – 分别设置grid-template-rowsgrid-template-columns

.container {
  grid-template: none | <grid-template-rows> / <grid-template-columns>;
}

grid-template-areas属性可以直接加在grid-template-rows当中,例如:

.container {
  grid-template:
    [row1-start] "header header header" 25px [row1-end]
    [row2-start] "footer footer footer" 25px [row2-end]
    / auto 50px auto;
}

以上代码如果写全了,就相当于:

.container {
  grid-template-rows: [row1-start] 25px [row1-end row2-start] 25px [row2-end];
  grid-template-columns: auto 50px auto;
  grid-template-areas: 
    "header header header" 
    "footer footer footer";
}

column-gap, row-gap

这些属性用来设置“网络线”的大小。也就是网格单元格之间的空隙的大小。

.container {
  /* standard */
  column-gap: <line-size>;
  row-gap: <line-size>;
}

比如:

.container {
  grid-template-columns: 100px 50px 100px;
  grid-template-rows: 80px auto 80px; 
  column-gap: 10px;
  row-gap: 15px;
}

将生成网格为:

gap

column-gap, row-gap两者的简写形式

.container {
  gap: <grid-row-gap> <grid-column-gap>;
}

例如:

.container {
  grid-template-columns: 100px 50px 100px;
  grid-template-rows: 80px auto 80px; 
  gap: 15px 10px;
}

如果只设置一个值的话,那么则说明column-gap, row-gap这两个属性的值是相等的。

.container {
  grid-template-columns: 100px 50px 100px;
  grid-template-rows: 80px auto 80px; 
  gap:10px;    //行,列的gap值都是10px
}

justify-items

该属性用来设置网格元素在行所在轴的排列方式。

  • start – 将网格元素与所在网格的开始处贴合对齐。
  • end – 将网格元素与所在网格的结束处贴合对齐。
  • center – 将网格元素置于所在网格的中间处。
  • stretch – 此项为默认值,即元素会自动撑满所在网格。
.container {
  justify-items: start | end | center | stretch;
}

例:

.container {
  justify-items: start;
}

.container {
  justify-items: end;
}

.container {
  justify-items: center;
}

.container {
  justify-items: stretch;
}

如果要单独设置某个元素的对方方式,那么可以对元素本身使用justify-self来设置。

align-items

justify-items相对应,align-items则是用来设置与justify-items相垂直的“列”

  • stretch – 此项为默认值,元素将在高度上撑满所在单元格。
  • start – 将网格元素与所在网格的开始处(顶部)贴合对齐。
  • end – 将网格元素与所在网格的结束处(底部)贴合对齐。
  • center – 将网格元素置于所在网格的中间(垂直方向)处。
  • baseline – 元素将会根据网格中文字的基线来进行对齐。
.container {
  align-items: start | end | center | stretch;
}

例:

.container {
  align-items: start;
}

.container {
  align-items: end;
}

.container {
  align-items: center;
}

.container {
  align-items: stretch;
}

如果要设置单个元素,那么可以使用align-self

place-items

align-itemsjustify-items的缩写形式。

值格式为:<align-items> / <justify-items>,如果只提供一个值,那么这上值将会同时作用于两个属性。

如果想要一个绝对居中的效果,那么用这个属性将会变的非常简单。

.center {
  display: grid;
  place-items: center;
}

上面的代码就相当于:

.center {
  display: grid;
  justify-items: center;
  align-items: center;
}

justify-content ,align-content

有时候,网格容器内的网格元素的总大小会小于容器的大小,就是说填不满整个网格容器。通常出现这种情况的原因就是网格元素在设置大小 的时候是使用了固定长度单位,比如px。这个时候,如果你想要设置这些元素的整体对齐方式,那么你就可以使用justify-conetntalign-conetnt。看名字是和 justify-align,align-items比较类似的,都一个设置行、一个设置列。只不过
*-content的属性值和之前会有一点点的区别:

  • start – 将所有的盒子元素做为一个整体向“网格容器”的开始处贴合对齐(行,列相同)。
  • end – 将所有的盒子元素做为一个整体向“网格容器”的结束处贴合对齐(行,列相同)。
  • center – 将所有的盒子元素做为一个整体在“网格容器”里进行居中。
  • stretch – 充满整个“网格容器”。
  • space-around – 将“剩余空间”平均分配到元素的中间和头尾,但是头尾末端的空隙是各元素中间空隙的一半。
  • space-between – 将“剩余空间”平均分配到元素的中间。
  • space-evenly – 将“剩余空间”平均分配到元素的中间和头尾。

justify-content

.container {
  justify-content: start;
}

.container {
  justify-content: center;
}

.container {
  justify-content: end;
}

.container {
  justify-content: stretch;
}

.container {
  justify-content: space-around;
}

.container {
  justify-content: space-between;
}

.container {
  justify-content: space-evenly;
}

align-content

.container {
  align-content: start;
}

.container {
  align-content: end;
}

.container {
  align-content: center;
}

.container {
  align-content: stretch;
}

.container {
  align-content: space-around;
}

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

.container {
  align-content: space-evenly;
}

place-content

此属性是 justify-contentalign-content 的缩写形式,值的格式为 <align-content> / <justify-content>。如果只提供一个值,则说这两个值相同。

grid-auto-columns, grid-auto-rows

这两具属性是用来控制自动生成的网格(也被称为隐式网格)大小的。什么是隐式网格?举个例子来说,假如我们使用grid-template-columsgrid-template-rows定义了一个两行两列的网格系统,在他们定义之内的网格称做显示网格。但是超出的两行两列的网格元素就称被之为隐式网格。

比如:

See the Pen
Untitled
by vvheat (@vvheat)
on CodePen.

上面的例子当中可以看到 2×2的网格是100*100的,多出来的两个就是“隐式网格”。其实只要网格元素不在grid-template-colums, grid-template-rows所定义的网格当中,那么它就会跑到隐式网格当中。

grid-auto-columns, grid-auto-rows的属性值其实和grid-template-colums, grid-template-rows的定义方法一样。

.container {
  grid-auto-columns: <track-size> ...;
  grid-auto-rows: <track-size> ...;
}

例子:

.container {
  grid-template-columns: 60px 60px;
  grid-template-rows: 90px 90px;
}

上面创建了一个2×2的显式网格。
假设里面现在有两个网格元素.item-a,.item-b,我们对它们做如下设置:

.item-a {
  grid-column: 1 / 2;
  grid-row: 2 / 3;
}
.item-b {
  grid-column: 5 / 6;
  grid-row: 2 / 3;
}

上面有关网格元素的属性方法我们还没有介绍,但其实很简单:


我们把.item-b放在了从第5条纵向网格线开始和第6条纵向网格线结束的这个网格区域,但这个区域我们之前没有进行定义过。所以它是隐式网格。那么我们就可以使用grid-auto-columns,grid-auto-rows这两个属性来进行设置像这样的隐式网格:

.container {
  grid-auto-columns: 60px;
}

grid-auto-flow

如果在你的网格系统里出现了没有显式设置的网格元素(野孩子),那么此属性就会派上用场,它会根据一些公式算法来控制这些“野孩子”自动排队。

grid-auto-flow的值可能会是:

  • row – 此为默认值,网格元素会自动填充每一行,在必要的时候会添加新行。
  • column – 网格元素会自动填充每一列,在必要的时候会添加新列。
  • dense – 这个属性值则会尽可能的自动填满所有的“漏洞”( dense 这个单词直译过来就是“浓密的;密度大的”)。
.container {
  grid-auto-flow: row | column | row dense | column dense;
}

注意,dense 只会改变项目的视觉顺序,所以可能导致它们无序显示。

例:

<section class="container">
  <div class="item-a">item-a</div>
  <div class="item-b">item-b</div>
  <div class="item-c">item-c</div>
  <div class="item-d">item-d</div>
  <div class="item-e">item-e</div>
</section>

下面我们来创建一个5列2行的网格系统,并且设置grid-auto-flowrow

.container {
  display: grid;
  grid-template-columns: 60px 60px 60px 60px 60px;
  grid-template-rows: 30px 30px;
  grid-auto-flow: row;
}

然后,只设置其中两个元素的网格位置。

.item-a {
  grid-column: 1;
  grid-row: 1 / 3;
}
.item-e {
  grid-column: 5;
  grid-row: 1 / 3;
}

因为我们设置了grid-auto-flow:row,所以网格会变成这样(注意我们没有进行设置位置的三个元素item-b,item-c,item-d是如何在可用的行空间里进行排列的,他们会依次在一行中排列):

如果我们设置grid-auto-flowcolumn,那么他们将会依次在一列中排列,如果排不下,则会跑到下一列去。

.container {
  display: grid;
  grid-template-columns: 60px 60px 60px 60px 60px;
  grid-template-rows: 30px 30px;
  grid-auto-flow: column;
}

Grid Item 网格元素相关属性

grid-column-start/end, grid-row-start/end

指定网格元素所在区域的起始位置,这个起始位置指的是网格线的位置。

  • <line> – 网格线的索引值,或者网格线的名称。
  • span <number> – 将占用的单元格数
  • span <name> – 根据提供的名字来进行填充
  • auto – 自动计算跨度进行放置网格元素,或者span 1设为其默认值
.item {
  grid-column-start: <number> | <name> | span <number> | span <name> | auto;
  grid-column-end: <number> | <name> | span <number> | span <name> | auto;
  grid-row-start: <number> | <name> | span <number> | span <name> | auto;
  grid-row-end: <number> | <name> | span <number> | span <name> | auto;
}

例:

.item-a {
  grid-column-start: 2;
  grid-column-end: five;
  grid-row-start: row1-start;
  grid-row-end: 3;
}

.item-b {
  grid-column-start: 1;
  grid-column-end: span col4-start;
  grid-row-start: 2;
  grid-row-end: span 2;
}

如果不指定grid-column-end/grid-row-end,那么默认会进行span 1的操作。
网格元素在设置过程中可能会出现重叠,你可以使用z-index属性来控制它们的显示顺序。

grid-column,grid-row

grid-column-start + grid-column-endgrid-row-start + grid-row-end的缩写形式。

.item {
  grid-column: <start-line> / <end-line> | <start-line> / span <value>;
  grid-row: <start-line> / <end-line> | <start-line> / span <value>;
}

例:

.item-c {
  grid-column: 3 / span 2;
  grid-row: third-line / 4;
}

同样,如果没有指定结束的网格线,那么默认表现将会是span 1

grid-area

根据由grid-template-areas定义的网格区域名来进行填充。也可以是grid-row-start + grid-column-start + grid-row-end + grid-column-end的缩写:

.item {
  grid-area: <name> | <row-start> / <column-start> / <row-end> / <column-end>;
}

例:

//根据名称
.item-d {
  grid-area: header;
}
//缩写形式
.item-d {
  grid-area: 1 / col4-start / last-line / 6;
}

justify-self

justify-items属性值取值一样,但是此值只是用来设置当前网格元素在单元格内的行方向排列方式。

例:

.item-a {
  justify-self: start;
}

.item-a {
  justify-self: end;
}

.item-a {
  justify-self: center;
}

.item-a {
  justify-self: stretch;
}

align-self

align-items属性值取值一样,但是此值只是用来设置当前网格元素在单元格内的列方向排列方式。

例:

.item-a {
  align-self: start;
}

.item-a {
  align-self: end;
}

.item-a {
  align-self: center;
}

.item-a {
  align-self: stretch;
}

place-self

jusitfy-selfalign-self的缩写形式。

.item-a {
  place-self: <align-self> / <justify-self>;
}

如果只提供一个值,则是同时设置这两个值。

例:

.item-a {
  place-self: center;
}

.item-a {
  place-self: center stretch;
}

特殊的单位 & 函数

fr 单位

在CSS Grid系统中,你可能会用到很多“分数单位” – fr 。比如:

grid-template-columns: 1fr 3fr;

大概可以理解成是25% 75%,但其实这么理解不是完全准确的。实际上,fr的最终值完全是根据“剩余空间”计算出来的 如果全是fr单位可以理解成百分比。如果向那些基于百分比的列添加padding,那么100%宽度还要加上padding(content-box 模型)。分数单位与其他单位结合起来也更友好:

grid-template-columns: 50px min-content 1fr;

定义尺寸的关键字

当我们设置行、列的大小时,除了可以使用一些长度单位(比如 px,rem,%...)之外,还可以使用一些如下关键字:

  • min-content: 根据里面的内容尽量计算出的最小宽度。比如有一行文字E pluribus unum,当我们设置了min-content时,这行文字会进行折行,那么此时这一行文字会变成三行,计算出的最小宽度应该就是内容当中pluribus的宽度,因为再小就放不下了。
  • max-content: 根据内容计算出的最大宽度。还是一行文字E pluribus unum,这个时候文字会在一行显示,这个时候宽度就是一行文字的大小了。

  • auto: 和fr单位的功能很像,但是当autofr碰到的时候,那么空间会优先分配给fr

See the Pen
Untitled
by vvheat (@vvheat)
on CodePen.

定义尺寸的函数

  • minmax():此函数用来控制你的网格元素尺寸的最大、最小值,因为有时候我们不希望网格元素没有约束的进行缩放。
    比如 : grid-template-columns: minmax(100px, 1fr) 3fr;
  • min(): 定义尺寸最小值。
  • max(): 定义尺寸最大值。
  • fit-content(): 根据公式 min(maximum size, max(minimum size, argument))计算出来的大小。

repeat()函数和一些“关键字”

见名知其意,它是用来帮我们重复输出值的,比如:

grid-template-columns:
  1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr;

/* easier: */
grid-template-columns:
  repeat(8, 1fr);

/* especially when: */
grid-template-columns:
  repeat(8, minmax(10px, 1fr));

我们也可以配合一些关键字来得到一些其它效果:

  • auto-fill: 如果网格容器在相关轴上具有确定的大小或最大大小,则重复次数是最大可能的正整数,不会导致网格溢出其网格容器。如果定义了,将每个轨道视为其最大轨道尺寸大小函数 ( grid-template-rowsgrid-template-columns用于定义的每个独立值。 否则,作为最小轨道尺寸函数,将网格间隙加入计算. 如果重复次数过多,那么重复值是 1 。否则,如果网格容器在相关轴上具有确定的最小尺寸,重复次数是满足该最低要求的可能的最小正整数。 否则,指定的轨道列表仅重复一次。
  • auto-fit: 行为与 auto-fill 相同,除了放置网格项目后,所有空的重复轨道都将折叠。空轨道是指没有流入网格或跨越网格的网格项目。(如果所有轨道都为空,则可能导致所有轨道被折叠。)折叠的轨道被视为具有单个固定轨道大小函数为 0px,两侧的槽都折叠了。为了找到自动重复的轨道数,用户代理将轨道大小限制为用户代理指定的值(例如 1px),以避免被零除。