Grid布局

382 阅读5分钟

grid 轨道(行和列)

  • grid-template-rows
grid-template-rows: 1fr 1fr;  /* 指定 2 行 宽 1fr*/
  • grid-template-columns
grid-template-columns: 1fr 1fr;  /* 指定 2 列 高 1fr*/

grid中的子项宽高默认根据 grid-template-rows 和 grid-template-columns 的值设定, 如果有多余的子项 (产生隐式网格), 按自身是的display类型适应。

repeat 函数

grid-template-columns: repeat(3, 1fr);

等价于

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

设置隐式网格的宽高

隐式网格:指子项数量超出的整个网格的数量的超出部分。如果只设置了display: grid, 那么整个网格都是隐式网格 (默认是一列多行)

  • 多余的行:grid-auto-rows
grid-auto-rows: 200px
  • 多余的列: grid-auto-columns
grid-auto-columns: 200px

网格

因为Grid会为我们创建带编号的网格线来让我们来定位每一个网格元素, 所以在设置子项合并的时候取值范围:

列:1 ~ 显示列数 + 1

行:1 ~ 显示行 + 1

例子:一个两行三列的网格, 列的取值范围(1 ~ 4), 行的取值范围(1 ~ 3)

image.png

合并行和列

这里的合并代表子项占多行或多列

子项设置 grid-column-start, grid-column-end, grid-row-start, grid-row-end, 或者使用简写 grid-area, 调整位置和合并。

  • 列:

grid-column-start: 网格元素从哪一列开始

grid-column-end: 网格元素从哪一列结束

grid-column: grid-column-start / grid-column-end

  • 行:

grid-row-start: 网格元素从哪一行开始

grid-row-end: 网格元素从哪一行结束

grid-row: grid-row-start / grid-row-end

注意:start和end必须一起出现才能达到合并的效果, 如果只设置一项, 那么就是在设置元素的位置

grid-area:上面行列属性的简写

例子:

/* row-start / column-start / row-end / column-end */
grid-area: 1 / 1 / 2 / 4; 
/* row-start / row-end */
grid-area: 1 / 2; 

span合并

span 表示占据几行/列, 不需要考虑网格线

/* 从默认开始位置合并2列 */
grid-column-start: span 2;  
/* 从默认开始位置合并2列 */
grid-column-end: span 2;
/* span表示占据几行,这里表示从2开始,占据2行,也就是网格线2到4 */
grid-area: 2 / span 2;

注意:如果 end 使用 span 超出了原有网格的列/行数, 会产生隐式网格

如:当前网格是两行三列, 给第一行的第一个元素设置 grid-column-end: span 4, 那么整个网格的就变成了两行四列

网格模板区域

为了更方便的合并, 通过给网格项目命名合并。

父级通过 grid-template-areas 设置网格别名。

子项通过 grid-area 使用网格别名。

以下例子相同的命名就会合并为一个网格, . . 表示1fr的空白。

.grid-box {
  border: 1px solid #999;
  width: 400px;
  height: 120px;
  margin: 20px;
  display: grid;
  grid-template-columns: repeat(9, 1fr);
  grid-template-areas:
    "hd hd hd hd hd hd hd hd hd"
    "sd sd sd main main main main . ."
    "sd sd sd ft ft ft ft ft ft";
}
.grid-box > div {
  background-color: bisque;
  border-radius: 4px;
  border: 1px solid #ccc;
}
.grid-box > div:nth-of-type(1){
  grid-area: hd;
}
.grid-box > div:nth-of-type(2){
  grid-area: ft;
}
.grid-box > div:nth-of-type(3) {
  grid-area: main;
}
.grid-box > div:nth-of-type(4) {
  grid-area: sd;
}

网格线的命名

.grid-box {
  grid-template-columns: [main-start] 1fr [content-start] 1fr [content-end] 1fr [main-end];
  grid-template-rows: [main-start] 40px [content-start] 40px [content-end] 40px [main-end];
}
.grid-box > div:nth-of-type(1) {
  grid-column-start: main-start;
  grid-column-end: main-end;
  grid-row-start: main-start;
  grid-row-end: content-start;
}
.grid-box > div:nth-of-type(2) {
  grid-column: main-start / content-start;
  grid-row: content-start / main-end;
}

网格单元和网格间距

grid-column-gapgrid-row-gap或者grid-gap

grid-gap: row-gap column-gap

gap: row-gap column-gap

不确定容器尺寸下的自动填充

  • 子项元素的超出父级的宽度会像 flex 一样自动换行, 前提是不固定列数

如果想要子项自动填满父级, 那么设置固定的列数就不太适合了, 可以使用 auto-fill 解决

/* 表示,每一列都是50px,但是具体有几列,需要根据子元素填充的情况来定,不足则空白 */
grid-template-columns: repeat(auto-fill, 50px);

如果不想要空白, 使用 minmax 函数解决

/* 最小宽度 50px 最大 自动撑满 */
grid-template-columns: repeat(auto-fill, minmax(50px, 1fr)) ;

盒子摆放顺序

grid-auto-flow: [ row | column ] || dense

  • row:先行后列的排序 (默认)
  • column:先列后行的排序
  • dense:空白填充, 即当出现宽度不足换行, 那么可能会出现空白区域, dense 就会将其他子项宽度可以小于等于空白区域的填充进去。 当然, 这样会打乱原有的子项顺序

row 和 column 类似于 flex 的 flex-direction

.grid-box > div {
    background-color: bisque;
    border-radius: 4px;
    border: 1px solid #ccc;
}

.grid-box {
    width: 200px;
    border: 1px solid #999;
    display: grid;
    gap: 2px;
    grid-template-columns: repeat(4, 1fr);
    grid-auto-rows: 50px;
     /*grid-auto-flow: row dense;*/
}
.grid-box > div:nth-of-type(1){
    grid-column-end: span 3;
}
.grid-box > div:nth-of-type(2n){
    grid-column-end: span 2;
    grid-row-end: span 2;
}

对齐

Grid 对齐方式和 flex 有相同的属性 justify-content,justify-items,align-content,align-item 等,另外还外加 place-content, place-items, place-self

  • justify-content, align-content: 针对的是父级的整个内容块

  • justify-items, align-items: 针对的是每个子项。会导致子项不再是自动撑满轨道, 宽高变成由内容自行撑开

  • place-content: align-content 属性和 justify-content 属性的合并简写形式, 顺序align、justify

  • place-items: align-items 属性和 justify-items 属性的合并简写形式, 顺序align、justify

覆盖

子项的宽高是不会影响到其他子项的布局, 即:当子项A的宽高设置过大, 已经占据到子项B位置, 子项B的位置不会发生改变, 可以通过设置 z-index 进行调整。

原因的是 grid-template-columns grid-template-rows grid-template-areas 等属性设置的是网格的轨道(行/列)大小, 子项的宽高是默认撑满轨道而已

参考文章