grid基础语法介绍(上)

《轴线与网格》里主要讲述了gridflex中,网格与轴线的基本概念,了解了这些基本概念之后,我们可以更轻松地对布局方式进行研究,这一篇文章主要描述grid布局中,定义在容器的相关属性。

由于我之前也没有真正接触和使用过grid,因此接下来的内容算是一些我个人的探索和学习笔记吧,其中部分参考国内外优秀的grid布局的相关文献,希望能在我写完、您研究完之后能够真正有所收获。

定义在容器的属性

disaplay

display属性定义了一个网格容器,容器是展现为行内或块状由所给定的值而决定,此时,他的所有子元素进入grid文档流,称为grid项目。

  1. .box {
  2. display: grid | inline-grid | subgrid;
  3. }
  • grid定义了一个网格容器,它以块级元素的形式显示。
  • inline-grid定义了一个网格容器,它以内联元素的形式显示。
  • subgrid定义了一个网格容器,这个网格容器是其父级网格容器的一个子项。它的行和列的大小从父级网格容器中获取。

grid-template-columns

grid-template-rows

grid-template-rowsgrid-template-columns定义了一个网格的列数、行数以及网格的大小。

  1. .box {
  2. grid-template-columns: <track-size> ... | <line-name> <track-size> ...;
  3. grid-template-rows: <track-size> ... | <line-name> <track-size> ...;
  4. }
  • 定义网格单元的宽高,其单位可以是一个长度(如pxemremvwvh)或百分比,也可以是网格中自由空间的份数(单位为fr)。
  • 定义网格线的名称,它不是必须值。可以一个你选择的任意名字,当没有显示设定时,它的名字以数字表示。

例如:

  1. .box {
  2. grid-template-columns: 40px 50px auto 50px 40px;
  3. grid-template-rows: 25% 100px auto;
  4. }

image

为了更好地语义化,我们可以给网格线指定一个名字,注意网格线命名时的中括号语法:

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

image

一根网格线可以有多个名字,例如在下面的例子中第二根线有两个名字:row1-end 和 row2-start,命名方式以空格来作为间隔。

  1. .box {
  2. grid-template-rows: [row1-start] 25% [row1-end row2-start] 25% [row2-end];
  3. }

众所周知:程序员是不喜欢写重复的代码的,如果我们定义了容器的重复部分,你可以使用CSS的repeat()方法来生成多个相同值:

  1. .box {
  2. grid-template-columns: repeat(3, 20px [col-start]) 5%;
  3. }

上面的代码等价于

  1. .box {
  2. grid-template-columns: 20px [col-start] 20px [col-start] 20px [col-start] 5%;
  3. }

fr是一个特殊的单位,它可以类似于设定flex-grow时,给网格容器中的自由空间设置为一个份数,举个例子,下面的例子将把网格容器的每个子项设置为三分之一:

  1. .box {
  2. grid-template-columns: 1fr 1fr 1fr;
  3. }

也是类似于flex-grow,自由空间是在固定子项确定后开始计算的(这里就如同flex-basis提前给予宽高那样),在下面的例子中自由空间是fr单位的总和但不包括50px

  1. .box {
  2. grid-template-columns: 1fr 50px 1fr 1fr;
  3. }

grid-template-areas

grid-template-areas可以配合grid-area定义一个显式的网格区域。grid-template-areas定义网格区域,然后使用grid-area调用声明好的网格区域名称来放置对应的网格项目。

如下列例子所示:grid-template-areas demo

  1. <section class="grid">
  2. <div class="title">title</div>
  3. <div class="nav">nav</div>
  4. <div class="main">main</div>
  5. <div class="aside">aside</div>
  6. <div class="footer">footer</div>
  7. </section>
  1. .grid {
  2. display: grid;
  3. grid-template-columns: 100px 100px 100px 100px 100px;
  4. grid-template-rows: 100px 100px 100px 100px;
  5. grid-template-areas: 'title title title title aside'
  6. 'nav main main main aside'
  7. 'nav main main main aside'
  8. 'footer footer footer footer footer';
  9. font-size: 30px;
  10. text-align: center;
  11. }
  12. .title {
  13. grid-area: title;
  14. background-color: blue;
  15. }
  16. .nav {
  17. grid-area: nav;
  18. background-color: yellow;
  19. }
  20. .main {
  21. grid-area: main;
  22. background-color: gray;
  23. }
  24. .aside {
  25. grid-area: aside;
  26. background-color: green;
  27. }
  28. .footer {
  29. grid-area: footer;
  30. background-color: pink;
  31. }

image

grid-column-gap

grid-row-gap

grid-column-gapgrid-row-gap定义了网格之间的间距。

  1. .box {
  2. grid-column-gap: <line-size>;
  3. grid-row-gap: <line-size>;
  4. }

例如:

  1. .box {
  2. grid-template-columns: 100px 50px 100px;
  3. grid-template-rows: 80px auto 80px;
  4. grid-column-gap: 10px;
  5. grid-row-gap: 15px;
  6. }

image

注意grid-column-gapgrid-row-gap定义的值不包括网格项目到容器边缘的间距。

justify-items

justify-items定义了网格子项的内容和列轴对齐方式,即水平方向上的对齐方式。

  1. .box {
  2. justify-items: start | end | center | stretch;
  3. }
  • start代表内容和网格区域的左边对齐。
  • end代表内容和网格区域的右边对齐。
  • center代表内容和网格区域的中间对齐。
  • stretch为默认值,代表填充整个网格区域的宽度。

显而易见,类似于flex布局方式,利用此属性,我们能很容易地实现水平居中了。

举例:

  1. .box {
  2. justify-items: start;
  3. }

image

  1. .box {
  2. justify-items: end;
  3. }

image

  1. .box {
  2. justify-items: center;
  3. }

image

  1. .box {
  2. justify-items: stretch;
  3. }

image

此外,我们可以通过对grid项目设定justify-self属性把这个行为设置到单独的网格子项。

align-items

类似于justify-itemsalign-items定义了网格子项的内容和行轴对齐方式,即垂直方向上的对齐方式。

  1. .box {
  2. align-items: start | end | center | stretch;
  3. }
  • start代表内容和网格区域的上边对齐。
  • end代表内容和网格区域的下边对齐。
  • center代表内容和网格区域的中间对齐。
  • stretch为默认值,代表填充整个网格区域的高度。

显而易见,类似于flex布局方式,利用此属性,我们能很容易地实现垂直居中了。

举例:

  1. .box {
  2. align-items: start;
  3. }

image

  1. .box {
  2. align-items: end;
  3. }

image

  1. .box {
  2. align-items: center;
  3. }

image

  1. .box {
  2. align-items: stretch;
  3. }

image

此外,我们可以通过对grid项目设定align-self属性把这个行为设置到单独的网格子项。

justify-content

实际上在使用中可能出现这种情况:网格总大小比它的网格容器的容量小,导致这个问题的原因可能是所有网格子项都使用了固定值,比如pxjustify-content属性定义了网格和网格容器列轴对齐方式(和align-content相反,它是和行轴对齐)。

  1. .box {
  2. justify-content: start | end | center | stretch | space-around | space-between | space-evenly;
  3. }

这个属性很类似于Flexboxjustify-content属性:

  • start代表网格在网格容器左边对齐。
  • end代表网格在网格容器右边对齐。
  • center代表网格在网格容器中间对齐。
  • stretch改变网格子项的容量让其填充整个网格容器宽度。
  • space-around代表在每个网格子项中间放置均等的空间,在始末两端只有一半大小。
  • space-between代表在每个网格子项中间放置均等的空间,在始末两端没有空间。
  • space-evenly代表在每个网格子项中间放置均等的空间,包括始末两端。

举例:

  1. .box {
  2. justify-content: start;
  3. }

image

  1. .box {
  2. justify-content: end;
  3. }

image

  1. .box {
  2. justify-content: center;
  3. }

image

  1. .box {
  2. justify-content: stretch;
  3. }

image

  1. .box {
  2. justify-content: space-around;
  3. }

image

  1. .box {
  2. justify-content: space-between;
  3. }

image

  1. .box {
  2. justify-content: space-evenly;
  3. }

image

align-content

类似于justify-contentalign-content属性定义了网格和网格容器行轴对齐方式。

  1. .box {
  2. align-content: start | end | center | stretch | space-around | space-between | space-evenly;
  3. }
  • start代表网格在网格容器上边对齐。
  • end代表网格在网格容器下边对齐。
  • center代表网格在网格容器中间对齐。
  • stretch改变网格子项的容量让其填充整个网格容器高度。
  • space-around代表在每个网格子项中间放置均等的空间,在始末两端只有一半大小。
  • space-between代表在每个网格子项中间放置均等的空间,在始末两端没有空间。
  • space-evenly代表在每个网格子项中间放置均等的空间,包括始末两端。

举例:

  1. .box {
  2. align-content: start;
  3. }

image

  1. .box {
  2. align-content: end;
  3. }

image

  1. .box {
  2. align-content: center;
  3. }

image

  1. .box {
  2. align-content: stretch;
  3. }

image

  1. .box {
  2. align-content: space-around;
  3. }

image

  1. .box {
  2. align-content: space-between;
  3. }

image

  1. .box {
  2. align-content: space-evenly;
  3. }

image

grid-auto-columns

grid-auto-rows

根据前面所学可知,grid-template-columnsgrid-template-rowsgrid-template-areas三个属性可以定义一个显式的网格,确定网格的轨道以及网格行数和列数的明确数量。
grid-auto-columnsgrid-auto-rows可以指定隐式网格。

  1. .box {
  2. grid-auto-columns: <track-size> ...;
  3. grid-auto-rows: <track-size> ...;
  4. }

因为隐式网格的概念比较抽象,这里举例子来进行说明:

我先写了以下代码:

  1. <div class="grid">
  2. <div class="box1">box1</div>
  3. <div class="box2">box2</div>
  4. <div class="box3">box3</div>
  5. <div class="box4">box4</div>
  6. </div>
  1. .grid {
  2. display: grid;
  3. grid-template-columns: 200px;
  4. grid-template-rows: 200px;
  5. text-align: center;
  6. font-size: 30px;
  7. }
  8. .box1 {
  9. background-color: pink;
  10. grid-column: 1;
  11. grid-row: 1;
  12. }
  13. .box2 {
  14. background-color: yellow;
  15. grid-column: 2;
  16. grid-row: 1;
  17. }
  18. .box3 {
  19. background-color: gray;
  20. grid-column: 1;
  21. grid-column: 2;
  22. }
  23. .box4 {
  24. background-color: blue;
  25. grid-column: 2;
  26. grid-row: 2;
  27. }

因为我们只给了网格容器一个网格单元,即我们只创建了一个1×1的网格,并且没有指定grid-auto-columnsgrid-auto-rows属性,在浏览器中渲染出来是这样的:

image

现在,我们可以通过grid-auto-columnsgrid-auto-rows属性,创建一个隐式的2×2的网格

给上述代码的.grid添加如下两条属性:

  1. grid-auto-columns: 300px;
  2. grid-auto-rows: 300px;

现在我们就能正常显示出这样的隐式网格了:

image

您可以点此查看demo。

grid-auto-flow

像刚才我们没有添加grid-auto-columnsgrid-auto-rows属性时,网格也类似于自动放置到了应该放置的位置了。

其实grid布局自身具有的自动布局算法会将网格子项自动放置起来,而grid-auto-flow属性控制自动布局算法如何工作。

  1. .box {
  2. grid-auto-flow: row | column | row dense | column dense
  3. }
  • row为默认值,代表自动布局算法在每一行中依次填充,只有必要时才会添加新行。
  • column代表自动布局算法在每一列中依次填充,只有必要时才会添加新行。
  • dense代表告诉自动布局算法如果更小的子项出现时尝试在网格中填补漏洞。

我们尽量不要将这个属性设置为dense,因为它可能让我们的页面布局产生混乱。

举个例子:

  1. <section class="container">
  2. <div class="item-a">item-a</div>
  3. <div class="item-b">item-b</div>
  4. <div class="item-c">item-c</div>
  5. <div class="item-d">item-d</div>
  6. <div class="item-e">item-e</div>
  7. </section>
  1. .container {
  2. display: grid;
  3. grid-template-columns: 60px 60px 60px 60px 60px;
  4. grid-template-rows: 30px 30px;
  5. grid-auto-flow: row;
  6. }

在这个例子中,我们创建了一个5×2的网格,并设置grid-auto-flowrow

但是当我们要网格中放置子项时,你只能为其中2个分配位置:

  1. .item-a{
  2. grid-column: 1;
  3. grid-row: 1 / 3;
  4. }
  5. .item-e{
  6. grid-column: 5;
  7. grid-row: 1 / 3;
  8. }

此时在页面中它会这样显示:

image

但如果我们把grid-auto-flow设定为column,它将呈现为这样的情况:

image

grid

grid为以下属性的合并写法:grid-template-rowsgrid-template-columnsgrid-template-areasgrid-auto-rowsgrid-auto-columnsgrid-auto-flow。它也可以设置grid-column-gapgrid-row-gap

  1. .box {
  2. grid: none | <grid-template-rows> / <grid-template-columns> | <grid-auto-flow> [<grid-auto-rows> [/ <grid-auto-columns>]];
  3. }

其中none代表一切值均为初始值。

举个例子,下面两段代码是等价的:

  1. .box {
  2. grid: 200px auto / 1fr auto 1fr;
  3. }
  1. .box {
  2. grid-template-rows: 200px auto;
  3. grid-template-columns: 1fr auto 1fr;
  4. grid-template-areas: none;
  5. }

下面两段代码也是等价的:

  1. .box {
  2. grid: column 1fr / auto;
  3. }
  1. .box {
  2. grid-auto-flow: column;
  3. grid-auto-rows: 1fr;
  4. grid-auto-columns: auto;
  5. }

注:就我个人而言,不建议使用合并写法,这样会让代码的维护者难以阅读。

参考资料: