css布局之 Grid

273 阅读4分钟

Grid

Grid 布局即网格布局,是一种新的布局,相比于 Flex 布局,要更加强大, Flex 是基于行列的排列组合,而 Grid 相当于拼图,在划分好格子的图上,进行每个子格子的填充,更加的灵活,强大。

兼容性

grid-compatibility.png

从这个图上来看,除了 IE 不支持外,其他主流浏览器只要不是过低版本,都支持 Grid 布局。

所有示例的代码在这里取

01. 初识 Grid 布局

代码

只展示最重要的部分,其他部分可以去仓库中查看

<style>
  ul {
    width: 400px;
    height: 200px;
    margin: 100px auto;
    border: 1px solid #ccc;
    /* 设置 grid 布局 */
    display: grid;
    /* 添加列 */
    grid-template-columns: 100px 100px 100px;
    /* 添加行 */
    grid-template-rows: 50px 50px 50px;
    /* 每个子项目之间的间隙 */
    grid-gap: 5px;
  }
</style>

<ul>
  <li>1</li>
  <li>2</li>
  <li>3</li>
  <li>4</li>
  <li>5</li>
  <li>6</li>
  <li>7</li>
  <li>8</li>
  <li>9</li>
</ul>

效果

grid-01.png

grid-01-debug.png

分析

  1. display: grid: 设置一个盒子或者一个行内块元素为 grid 布局,
  2. grid-template-columns:设置一个容器的网格有几列;
  3. grid-template-rows:设置一个容器的网格有几列;
  4. grid-gap:设置网格行与列之间的间隙(gutters),该属性是 grid-row-gap(行间距) and grid-column-gap(列间距)的简写形式,

2. 使用 repeat 简化行列的设置和合并子项目

代码

<style>
  .warpper {
    display: grid;
    grid-template-columns: repeat(3, 100px);
    grid-template-rows: repeat(2, 50px);
    grid-gap: 5px;
  }

  .item-merge {
    /* 子项目开始与结束位置 */
    grid-column-start: 1;
    grid-column-end: 3;
  }
</style>

<ul class="warpper">
  <li>1</li>
  <li>2</li>
  <li>3</li>
  <li>4</li>
  <li>5</li>
  <li>6</li>
</ul>

<h2>合并子元素</h2>
<ul class="warpper">
  <li>1</li>
  <li>2</li>
  <li>3</li>
  <li class="item-merge">4</li>
  <li>6</li>
</ul>

效果

grid-02.png

分析

  1. repeat(): 可以通过 repeat 函数简写行列的设置,第一个参数是一个数字,表示多少列,第二个参数表示大小,它可以是一个数,也可以是一个模式,如:repeat(2, 100px 50px 100px) == 100px 50px 100px 100px 50px 100px;

grid-02-layout.png

  1. grid-column-*: 设置子项目的起始位置,是依据网格来的,如:*-start: 1, *-end: 3,表示该子项目占据 1 ~ 3 之间的空间;
  2. grid-row-*: 同上,只是方向不同。

3. 实现等分排列

代码

<style>
  .wrapper {
    display: grid;
    /* 设置网格 */
    grid-template-columns: 100px 1fr 2fr;
    grid-template-rows: 1fr 2fr 1fr;
    grid-gap: 5px;
  }
</style>

<ul class="wrapper">
  <li>1</li>
  <li>2</li>
  <li>3</li>
  <li>4</li>
  <li>5</li>
  <li>6</li>
  <li>7</li>
  <li>8</li>
  <li>9</li>
</ul>

效果

grid-03.png

分析

grid 布局中,支持 fr 这个新的单位,它的效果是,用来等分不固定的空间,比如:100px 1fr 2fr,它的效果是,去掉固定的 100px 与间隙,剩下的空间等分成 3 份, 1fr 指一份。

4. 固定子项目大小后,尽可能多的使用空间

代码

<style>
  .warpper {
    display: grid;
    grid-template-columns: repeat(auto-fill, 90px);
    grid-template-rows: 50px 50px 50px;
  }
</style>

<ul class="warpper">
  <li>1</li>
  <li>2</li>
  <li>3</li>
  <li>4</li>
  <li>5</li>
  <li>6</li>
  <li>7</li>
  <li>8</li>
  <li>9</li>
</ul>

效果

grid-04.png

分析

repeat 函数与 auto-fill 关键字的组合使用,体现在,当子项目大小固定时,列不去固定,而是尽可能的去铺满剩余的空间,当剩下的空间不够一个子项目时,换行。

5. 按区域布局

这种布局方式,完全类似与拼图,划分好网格后,按照想要的内容,放置在对应的格子。

代码

<style>
  .warpper {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    grid-template-rows: repeat(3, 1fr);
    grid-template-areas:
      "a a a"
      "b b ."
      ". c c";
  }
  .item-a {
    grid-area: a;
  }
  .item-b {
    grid-area: b;
  }
  .item-c {
    grid-area: c;
  }
</style>

<ul class="warpper">
  <li class="item-b">1</li>
  <li class="item-c">2</li>
  <li class="item-a">3</li>
</ul>

效果

grid-05.png

分析

grid-template-areas 用来给网格的每个格子设置名字,其中使用 . 代替的,表示这个格子不适用;然后再子项目中添加 grid-area: name,即可将子项目放到对应的格子上。

相邻的格子使用同一个名字,表示可以合并,但是不可以出现 a . a 这种形式的命名。

6. 容器内对齐方式

代码

<style>
/* 容器内对齐方式 */
.warpper1 {
  display: grid;
  /* 设置网格 */
  grid-template-columns: 100px 100px 100px;
  grid-template-rows: 50px 50px 50px;
  grid-gap: 5px;

  /* 容器内布局 */
  justify-content: space-between;
  align-content: space-between;
}

.warpper2 {
  display: grid;
  /* 设置网格 */
  grid-template-columns: 100px 100px 100px;
  grid-template-rows: 50px 50px 50px;
  grid-gap: 5px;

  /* 子容器内部对齐方式 */
  justify-items: center;
  align-items: center;
}

.warpper2 li {
  width: 80px;
  height: 40px;
}
</style>

<h2>容器内部对齐方式</h2>
<ul class="warpper1">
  <li>1</li>
  <li>2</li>
  <li>3</li>
  <li>4</li>
  <li>5</li>
  <li>6</li>
  <li>7</li>
  <li>8</li>
  <li>9</li>
</ul>

<h2>子容器内盒子对齐方式</h2>
<ul class="warpper2">
  <li>1</li>
  <li>2</li>
  <li>3</li>
  <li>4</li>
  <li>5</li>
  <li>6</li>
  <li>7</li>
  <li>8</li>
  <li>9</li>
</ul>

效果

grid-06.png

分析

justify-contentalign-content 类似于 flex,设置容器的对齐方式,元素内容没有铺满的情况下才生效,效果就是 warpper1;

justify-itemsalign-items 设置每个格子内部的排列方式,也在在格子没有铺满的情况下才生效,效果就是 wrapper2

7. 自适应剩余空间

代码

<style>
  .wrapper1 {
    display: grid;
    /* 设置网格 */
    grid-template-columns: 100px auto 100px;
    grid-template-rows: 50px auto 50px;
    grid-gap: 5px;

    /* 容器内布局 */
    /* justify-content: space-between; */
    align-content: space-between;
  }

  .wrapper2 {
    display: grid;
    /* 设置网格 */
    grid-template-columns: 100px auto 100px;
    grid-template-rows: 50px auto 50px;
    grid-gap: 5px;
  }
</style>

<h2>添加对齐方式</h2>
<ul class="wrapper1">
  <li>1</li>
  <li>2</li>
  <li>3</li>
  <li>4</li>
  <li>5</li>
  <li>6</li>
  <li>7</li>
  <li>8</li>
  <li>9</li>
</ul>

<h2>不添加对齐方式</h2>
<ul class="wrapper2">
  <li>1</li>
  <li>2</li>
  <li>3</li>
  <li>4</li>
  <li>5</li>
  <li>6</li>
  <li>7</li>
  <li>8</li>
  <li>9</li>
</ul>

效果

grid-07.png

分析

auto 关键字,可以实现对剩余空间的利用,让子元素铺满剩余空间,但是它与对齐方式 *-content 冲突,如果设置了对应轴的对齐方式,那么它只会展示设置的空间大小,或者是最小的空间(在没有设置的情况下,你占据的大小,由子元素撑起)。

8. 子容器排列方式

代码

<style>
  .wrapper1 {
    display: grid;
    grid-template-columns: repeat(3, 100px);
    grid-template-rows: repeat(3, 50px);
    grid-gap: 5px;
    grid-auto-flow: column;
  }

  .wrapper2 {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    grid-template-rows: repeat(3, 50px);
    grid-gap: 5px;
    grid-auto-flow: row;
  }
  .wrapper3 {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    grid-template-rows: repeat(3, 50px);
    grid-gap: 5px;
    grid-auto-flow: row dense;
  }

  .wrapper2 li:nth-of-type(-n+3),.wrapper3 li:nth-of-type(-n+3) {
    grid-column-start: span 2;
  }
</style>

<h2>从上到下布局</h2>
<ul class="wrapper1">
  <li>1</li>
  <li>2</li>
  <li>3</li>
  <li>4</li>
  <li>5</li>
  <li>6</li>
</ul>

<h2>从左到右布局,但排不下时</h2>
<ul class="wrapper2">
  <li>1</li>
  <li>2</li>
  <li>3</li>
  <li>4</li>
  <li>5</li>
  <li>6</li>
</ul>

<h2>dense 布局</h2>
<ul class="wrapper3">
  <li>1</li>
  <li>2</li>
  <li>3</li>
  <li>4</li>
  <li>5</li>
  <li>6</li>
</ul>

效果

grid-08.png

分析

grid-auto-flow 能够定义格子的排列方式,也就是从左到右从上到下;虽然大部分的时候,布局都是合理的,但当有些特殊情况,出现一行还剩余空间,但是摆不下下一个元素的情况,使用 dense ,会将后面内容,逐个试着放进去,如何能放进去,则停止,继续之前的排列顺序。

总结:

grid.png