CSS知识点梳理(13)-网格布局

创建网格容器

  • 网格容器(grid container)是一个为其内容定义网格格式上下文(grid formatting context)的元素。

  • 网格又 2 种,dispaly:grid;dispaly:inline-grid;。wang’g
    Grids and inline grids

  • 被浮动的元素不会侵入网格容器,即网格不会滑动至浮动元素下
    Floats interact differently with blocks and grids

  • 网格容器的边距不会与其后代元素(第一个或最后一个子元素)的边距 折叠。

基本网格术语

Grid component

  • 网格容器(grid container)是一个建立网格格式上下文的盒子,并根据网格布局规则布局元素的区域。
  • 网格项(grid item)是 在网格格式上下文中参与网格布局的内容。通常是网格容器的子元素,也可以是匿名的文本。
  • 网格轨道(grid track)是两个相邻网格线之间的空间。换句话说,就是一个网格行(grid row)网格列(grid column)
  • 网格单元格(grid cell)是由四条网格线限定的空间,类似于表格单元格。网格单元格不能直接用 CSS 网格属性来控制。
  • 网格区域(grid area)是由一个或多个网格单元格组成的一个矩形区域。网格区域可以通过 CSS 网格属性直接控制。
  • 网格轨道,网格单元格,网格区域完全由网格线构成,它不必与网格项对应,不需要在每一个网格区域都填入一个网格项

网格线的布局

网格线的控制,先从两个密切相关的属性开始grid-template-rows,grid-template-columns

  • 网格线可以通过编号、命名或将它们混合在一起来引用。
    Grid-line numbers and names

  • 固定宽度的网格轨道

    1
    2
    3
    4
    5
    6
    7
    8
    #grid {
    display: grid;
    grid-template-columns: 200px 50% 100%;
    }
    #grid {
    display: grid;
    grid-template-columns: [start col-a] 200px [col-b] 50% [col-c] 100px [stop end last];
    }

    Grid-line name

  • 弹性网格轨道

    • fr单位,在一系列长度值周分配剩余空间,如果指定了多个部分,则剩余空间根据各自的系数按比例分配。例如grid-template-columns: 1fr 1fr 1fr,则网格容器的宽度 3 等分,每个列的宽度各占 1 份。
  • minmax(min,max)定义了一个长宽的闭区间,与网格布局一起使用。

    • 每个参数,可以是<length>(非负长度)<percentage><flex>max-content(网格轨道长度自适应内容最大的那个单元格)min-content(网格轨道长度自适应内容最小的那个单元格)auto之一。
    • 如果最大值小于最小值,则最大值被忽略,其被看成最小值
    • <flex>值最为最小值无效。单位为fr,指定网格轨道弹性布局的系数值,并按其系数值比例均匀分配剩余空间
    • auto作为最大值,等价于max-content,作为最小值,表示网格轨道中单元格最小长宽(min-width, min-height)的最大值。
  • fit-content(argument)类似于minmax(min-content, max-content),只是参数的值设置了一个上限。等价于min(max-content, max(min-content, argument))

    1
    2
    3
    4
    5
    #fit-content {
    dislay: grid;
    grid-template-columns: fit-content(50ch) fit-content(50ch) fit-content(50ch);
    font-family: monospace;
    }

    Sizeing grid tracks with fit-content()

    Fitting to wide content
    第二列中图片宽 500px,比 50ch 更宽。max(min-content,50ch)的结果是min-content,500pxmin(max-content,500px)结果是 500px。所有第二列500px 宽

  • repeat(n,width1,width2, ... windthN ),重复网格线

    1
    2
    3
    4
    #grid {
    display: grid;
    grid-template-columns: repeat(4, 10px [col-start] 250px [col-end]) 10px;
    }

    repeated columns with named grid lines

  • auto-fill,创建一个简单模式并重复,直到填满网格容器

    1
    2
    3
    4
    #grid {
    display: grid;
    grid-template-columns: repeat(3,20em) repeat(auto-fill,2em);
    }

    一个也可以编写grid-template-columns: repeat(auto-fill,2em) repeat(3,20em);,因为网格布局算法首先将空间分配给固定轨道,然后再用自动重复轨道填充剩余空间。
    Auto-filling columns next to fixed columns

网格区域(grid-template-areas)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#grid {
display: grid;
grid-template-areas:
"h h h h"
"l c c r"
"l f f f"
}
#grid {
display: grid;
grid-template-areas:
"header header header header"
"leftside content content rightside"
"leftside footer footer footer"
}

grid cells identifiers

  • grid-template-areas值中的每一个网格标识符对应于一个网格单元格,具有相同名称的单元格会合并到一个单独区域,**且该区域必须是矩形,如果是其他形状,则整个样式template无效,例如grid-template-areas: "h h h h" "l c c r" "l l f f",l区域的形状不是矩形,像一个L 形**。
  • 如果只希望定义一些网格单元格作为网格区域,而不标记其他单元格,则使用.字符来填充那些未命名的单元格。
    1
    2
    3
    4
    5
    6
    7
    #grid {
    display: grid;
    grid-template-areas:
    "header header header header"
    "left ... ... right"
    "footer footer footer footer"
    }
    grid with some unnamed grid cells

将元素附加到网格

  • 使用列线、行线 grid-row-start,grid-row-end,grid-column-start,grid-column-end,即“把元素的边缘依附于网格线”

    • 使用网格线编号
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      .grid {
      display: grid;
      width: 50em;
      grid-template-rows: repeat(5,5em);
      grid-template-columns: repeat(10,5em);
      }
      .one {
      grid-row-start:2;
      grid-row-end: 4;
      grid-column-start: 2;
      grid-column-end: 4;
      }
      .two {
      grid-row-start:1;
      grid-row-end: 3;
      grid-column-start: 5;
      grid-column-end: 10;
      }
      .three {
      grid-row-start:4;
      grid-column-start: 6;
      }
      attaching elements to grid  lines
    • 使用span关键字,表示跨越多少网格轨道,例如上例
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      .one {
      grid-row-start: 2;
      grid-row-end: span 2;
      grid-column-start: 2;
      grid-column-end: span 2;
      }
      .two {
      grid-row-start: 1;
      grid-row-end: span 2;
      grid-column-start: 5;
      grid-column-end: span 5;
      }
      .three {
      grid-row-start: 4;
      grid-row-end: span 1;
      grid-column-start: 6;
      grid-column-end: span; // span 后缺少数字,默认为 1
      }
    • 使用网格线名称
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      #grid {
      display: grid;
      grid-template-areas:
      "header header header header"
      "leftside content content rightside"
      "leftside footer footer footer"
      }
      #masthead {
      grid-row-start: header;
      grid-column-start: header;
      grid-row-end: header;
      }
      #sidebar {
      grid-row-start: 2;
      grid-row-end: 4;
      grid-column-start: leftside / span 1;
      }
      #main {
      grid-row-start: content;
      grid-row-end: content;
      grid-column-start: content;
      }
      #navbar {
      grid-row-start: rightside;
      grid-row-end:3;
      grid-column-start: rightside;
      }
      #footer {
      grid-row-start: 3;
      grid-row-end: span 1;
      grid-column-start: footer;
      grid-column-end: footer;
      }
      在定义网格区域时,浏览器会根据单元格名称,会使用name-startname-end给 其两边的网格线命名。所以grid-column-start: header;是等价于grid-column-start: header-start;
    • grid-columngrid-column简写属性.
      grid-column: start / endgrid-column-startgrid-column-end的简写属性.
  • 使用网格区域 grid-area,将元素分配到 先前定义的网格区域

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    #grid {
    display: grid;
    grid-template-areas:
    "header header header header"
    "leftside content content rightside"
    "leftside footer footer footer"
    }
    #masthead {grid-area: header;}
    #sidebar {grid-area: leftside;}
    #main {grid-area: content;}
    #navbar {grid-area: rightside;}
    #footer {grid-area: footer;}

    grid-area属性是grid-row-start, grid-column-start, grid-row-end,grid-column-end的简写属性。例如:

    1
    2
    3
    item8 {
    grid-area: 1 / 2 / 5 / 6;
    }

    item8开始于 row-line 1,column-line 2,结束于row-line 5,column-line 6
    grid-area: 1/2/5/6

网格流

如果没有显示的放置网格项,则自动将它们放置到网格中。在有效的网格流中,网格项被放置在第一个适合它的区域。最简单的情况就是按顺序填充一个网格轨道,一个网格项接着一个。如果有显示的和自动放置的网格项混合,后者必须围绕着前者工作。

  • grid-auto-flow定义了网格流模式,行优先 或 列优先

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    #grid {
    display: grid;
    width: 45em;
    height: 8em;
    grid-auto-flow: row;
    }
    #grid li {
    grid-row: auto;
    grid-column: auto;
    }

    row-oiented grid low

  • 当网络流中的元素大小超出网格项。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    #grid {
    display: grid;
    grid-template-rows: repeat(3, 50px);
    grid-template-columns: repeat(4, 50px);
    grid-auto-rows: 50px;
    grid-auto-columns: 50px;
    }
    img {
    grid-row: auto;
    grid-column: auto;
    }
    img.wide {
    grid-column: auto / span 2;
    }
    img.tall {
    grid-column: auto / span 2;
    }

    grid flow pattern

    • 在网格流中,如果一个网格单元格的空间不足放置下一个网格项,则网格项会跨域多个网格单元格。
    • 在行的网格流中,其工作方式是,从左到右遍历每一行,如果有单元格空中,就把网格项放在那里。所以,item 13 在 item 11 的右边
    • dense关键字会让网格流中网格项放置的更加紧密,grid-auto-flow: row dense;,grid-auto-flow: column dense
      dense flow pattern

自动的网格线

当一个网格项脱离边缘时,会根据需求添加行或列,以满足相关项的布局。一般情况下,自动添加的行或列的是需要的最小大小(即内容大小)。如果想对它们的大小施加更多控制,可以使用grid-auto-rowsgrid-auto-columns。如下图左边设置了grid-auto-row大小,右边没有。
Grid with and without auto-row sizing

grid 属性简写

该语法比较复杂,不建议使用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#grid {
grid: "header header header header" 3em
". content sidebar ." 1fr
"footer footer footer footer " 5em /
2em 3fr minmax(10em, 1fr) 2dm;
}
// 等价于
#grid {
grid-template-areas: "header header header header"
". content sidebar ."
"footer footer footer footer";
grid-template-rows: 3em 1fr 5em;
grid-template-columns: 2em 4fr minmax(10em, 1fr) 2em;
}

Creating a grid with the grid shorthand

网格项(网格轨道)之间间隔

gutter就是两个网格轨道之间的空间,就像通过扩展网格线之间的实际宽度。
通过grid-row-gapgrid-column-gap

  • grid-gap属性简写<grid-row-gap> <grid-column-gap>
    1
    2
    3
    4
    5
    6
    #grid {
    display: grid;
    grid-template-rows: 5em 5em;
    grid-template-columns: 15% 1fr 1fr;
    grid-gap: 12px 2em;
    }
    Defining grid gutter

网格项与盒模型

  • 基本工作原理:元素通过它的 margin 边缘来与网格连接。正边距将元素的可见部分从其占用的网格区域内推,负边距相反。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    #grid {
    display: grid;
    grid-template-rows: repeat(2,100px);
    grid-template-columns: repeat(2, 200px);
    }
    .box02 {
    margin: 25px;
    }
    .box03 {
    margin: -25px 0;
    }

    grid items with margins

  • 同块级布局相似,在网格布局中,也可以使用marginauto来将元素居中。

    1
    2
    3
    4
    5
    6
    .i01 {margin: 10px;}
    .i02 {margin: 10px; margin-left: auto};
    .i03 {margin: auto 10px auto auto};
    .i04 {margin: auto};
    .i05 {margin: auto auto 0 0};
    .i06 {margin: 0 auto};

    Various auto-margin alignments

  • 网格项是绝对定位;如果已经定义了网格线的开始和结束,则该网格区域被用作为包含块和定位上下文,而网格项将定位在该上下文中。这意味着偏移量属性是根据网格区域计算的

    1
    2
    3
    4
    5
    6
    7
    8
    9
    .exel {
    grid-row: 2 / 4;
    grid-column: 2 / 5;
    position: absolute;
    top: 1em;
    bottom: 15%;
    left: 35px;
    right: 1rem;
    }

    Absolutely positioning a grid item

对齐控制

网格布局的对齐方式同弹性盒子布局很相似。

Property Aligins Applied to
justify-content The entire grid in the inline(horizontal) direction Grid container
justify-items All grid items in the inline direction Grid container
justify-self A grid item in the inline direction Grid items
align-self A grid item in the block(vertical) direction Grid items
align-items All grid items in the block direction Grid container
align-content The entire grid in the block direction Grid container
  • 单个 item 的 对齐方式,justify-self, align-self
    Self alignment in the inline and block directions

  • 所有items的对齐方式,justify-items,align-items
    Center all the grid items

  • 整个grid的对齐方式,justify-content,align-content
    distributing grid items horizontally

层级与顺序

  • 网格项在视觉上的重叠顺序,就是在文档源中的顺序。
  • 同定位一样,可以使用z-index来调整元素在 z 轴上的位置。
  • 网格项的order属性也会影响其重叠顺序。