基本格子

<div class="box">
    <div class="item1">item1</div>
    <div class="item2">item2</div>
    <div class="item3">item3</div>
    <div class="item4">item4</div>
    <div class="item5">item5</div>
</div>
.box {
  display: grid;
}

父元素设置grid,只有第一级的子元素会受到grid布局影响,默认情况下,子元素的宽度都会占据一整行的宽度。哪怕子元素是一个inline元素。

控制每列的格子宽度

grid可以理解为把table布局的功能提取为css了,并且加以改进,更加适合现代化的复杂布局。

那么既然是table,自然可以配置每行有多少个格子,每个格子的大小了,这个配置会影响到每列对应的格子,效果和控制table的th宽度一样,th宽度会影响到它下面的tbdoy的td宽度。

.box {
  display: grid;
  grid-template-columns: 200px  150px  20%;
}

这里表示每行有三个格子,每个格子对应的宽度分别为:200px 150px 20%;当页面宽度足够的时候,右侧会出现空白,不会有元素像流体布局那样自动再后面追加,这也符合table布局的情况。

自适应宽度

如果我想占据剩余的宽度,我们可以使用fraction;这个单位和flex的flex-grow有异曲同工之处,都是占据剩余宽度,根据大小来进行等比分配。

.box {
  display: grid;
  grid-template-columns: 200px  2fr  20% 1fr;
}

这就表示第二个格子和第四个格子会占据剩余的宽度,并且按照2:1的比例分配。

控制每行的高度

.box {
    display: grid;
    grid-template-columns: 200px 2fr 20% 1fr;
    grid-template-rows: 50px 30px;
}

这里表示两行格子,第一行50px高,第二行30px高;

如果有第三行,此时我们没有设置,那么就会遵循默认设置,一般是内容多高就多高。

占据剩余高度

同样也是使用fraction;但是需要注意的是,父级有设置高度或者它有“高度”,而不是靠内容撑起来的,不然是无效的。

.box {
    height: 100vh;
    display: grid;
    grid-template-columns: 200px 2fr 20% 1fr;
    grid-template-rows: 50px 30px 1fr;
}

合并格子

其实和table的合并格子差不多,只是grid的合并,是需要配置分割线序号的。

浏览器开启显示序号更方便grid调试。

假如我们需要item3占据item4的位置

.item3 {
    background-color: burlywood;
    grid-column-start: 3;
    grid-column-end: 5;
}

假如我们还需要item3往下占据一行

.item3 {
    background-color: burlywood;
    grid-column-start: 3;
    grid-column-end: 5;
    grid-row-start: 1;
    grid-row-end: 3;
}

控制占据的分割线起始位置来达到效果,有点像js里字符串的截取,字符是从0开始,他这是从1开始。

auto 弹性系数

如果我们设置一些固定的行数或者列数,希望最后一个或者某一个能自动填满,那么一般推荐使用auto

但是多个auto他们不一定是等比分配的,所以,如果你有多个需要等比分配,fraction更加适合

.box {
    display: grid;
    grid-template-columns: 200px 150px 20% auto;
    grid-template-rows: 50px auto;
}

如果fractionauto同时存在,fraction权重会更大,因为auto代表剩余,但是剩余其实已经被fraction占用了,如果格子没有内容,auto会导致格子宽或者高为0;

常用的两个css函数

重复repeat

grid-template-columns设置几个就有几列,如果我想要5个相同大小的格子,那么就要写5次。

.box {
    display: grid;
    grid-template-columns: 20% 20% 20% 20% 20%;
}

利用repeat函数我们可以很方便的创建

.box {
    display: grid;
    grid-template-columns: repeat(5, 20%);
}

命名网格线

这个知识点可以看完下面的命名网格线再来看,这里是关于repeat与命名的使用。

由于repeat是重复,如果我们这么写:

.box {
    display: grid;
    grid-template-columns: repeat(5, [col-start] 20% [col-end]);
}

实际上会使得网格线的名称发生了重复,大概生成了如下的结构:

[col-start] [col-end col-start] [col-end col-start] [col-end col-start] [col-end col-start] [col-end]

生成这么6条线,且名字都是一样,这在使用的时候怎么区分?

css的做法是,如果名字一样,后面再接一个它的顺序,比如我要第二条col-start开始到第二条col-end结束,那么就需要这么写:

.item3 {
    background-color: burlywood;
    grid-column-start: col-start 2;
    grid-column-end: col-end 2;
}

最小最大minmax

如果我们希望有一个格子,它的最小是10px;最大是200px;我们常常会使用:min-height、max-height这种形式,利用函数我们可以很简单的配置

.box {
    height: 100vh;
    display: grid;
    grid-template-columns: repeat(5, 20%);
    grid-template-rows: minmax(50px, 200px) minmax(100px, 1fr);
}

minmax第一个参数是最小值,第二个是最大值,当空间足够,就会使用最大值,不够则使用最小值,当已经不能再小的时候,就会固定,不会在继续缩小了。

这个效果有点像我们平时这么设置:

.container {
  width:200px;
  max-width: 1200px;
}

合并格子补充

指定合并的格子数量

合并格子的end参数可以像table那样,直接指定合并几格子

.item3 {
    background-color: burlywood;
    grid-column-start: 3;
    grid-column-end: span 2;
    grid-row-start: 1;
    grid-row-end: span 2;
}

span表示合并格子,后面接合并的数量。

-1值

如果想让一个格子占据一行,我们可以可以使用-1值,在不知道每行有多少个格子的情况下。

.item2 {
    background-color: aquamarine;
    grid-column-start: 1;
    grid-column-end: -1;
}

正数的1是从左边开始,负数的1是从右边开始。

重叠与层级

grid布局是支持元素重叠的,比如item3占据的上下两行,而item2只是横向占据一整行,那么grid会自动判断,item3的权重更高,item2就只能往下移动。

.item2 {
    background-color: aquamarine;
    grid-column-start: 1;
    grid-column-end: -1;
}

.item3 {
    background-color: burlywood;
    grid-column-start: 3;
    grid-column-end: span 2;
    grid-row-start: 1;
    grid-row-end: span 2;
}

因为item2没有设置row的具体,那么就会被自动往下移动已符合css占据一行的要求,但是如果item也指定了row,那么就会发生重叠,且重叠的层级是根据html元素顺序来得,元素在后面,层级就越高,并且支持z-index直接控制层级。

.item2 {
    background-color: aquamarine;
    grid-column-start: 1;
    grid-column-end: -1;
    grid-row-start: 2;
    grid-row-end: 3;
}

.item3 {
    background-color: burlywood;
    grid-column-start: 3;
    grid-column-end: span 2;
    grid-row-start: 1;
    grid-row-end: span 2;
}

grid一般是不允许重叠的,如果需要重叠,我们就需要像上面那样指定固定位置。

由于item3在item2后面,所以重叠时他在上面,我们可以给item2指定z-index层级,让他显示在上面。

.item2 {
    background-color: aquamarine;
    grid-column-start: 1;
    grid-column-end: -1;
    grid-row-start: 2;
    grid-row-end: 3;
    z-index: 1;
}

命名网格线

网格线是有序号的,但是我们可以为其自定义命名,且同一条线可以有多个名字,做法就是数值前面用[名字]设置。

.box {
    height: 100vh;
    display: grid;
    grid-template-columns: repeat(3, 20%) auto;
    grid-template-rows: [row-start] minmax(50px, 200px) [row-center row-bottom] minmax(100px, 200px) [row-end];
}

多个命名用空格分割,命名设置好后,就可以使用名称来定义范围了

.item3 {
    background-color: burlywood;
    grid-column-start: 3;
    grid-column-end: span 2;
    grid-row-start: row-start;
    grid-row-end: row-end;
}

简写

grid-column为简写形式,第一个值为start,第二值为end,用/分隔。

.item3 {
    background-color: burlywood;
    /* grid-column-start: 3;
      grid-column-end: 5; */
    grid-column: 3 / 5;  
}

grid-row也是一样。

.item3 {
    background-color: burlywood;
    /* grid-row-start: 1;
      grid-row-end: -1; */
    grid-row: 1 / -1;
}

grid-column和grid-row也能合并成简写形式,只不过对顺序有要求

grid-area: grid-row-start / grid-column-start / grid-row-end / grid-column-end;
.item3 {
    background-color: burlywood;
    grid-area: 1 / 3 / -1 / 5;
}

行间距与列间距

行间距

.box {
    height: 100vh;
    display: grid;
    grid-template-columns: repeat(3, 20%) auto;
    grid-template-rows: 50px 100px;
    grid-row-gap: 20px;
}

grid-row-gap只接受一个值,每行的间隔都是统一的

列间距

.box {
    height: 100vh;
    display: grid;
    grid-template-columns: repeat(3, 20%) auto;
    grid-template-rows: 50px 100px;
    grid-column-gap: 20px;
}

一样也是只支持一个值。

简写

.box {
    height: 100vh;
    display: grid;
    grid-template-columns: repeat(3, 20%) auto;
    grid-template-rows: 50px 100px;
    grid-gap: 20px 20px;
}

grid-gap第一个值是行间距,第二个值是列间距,如果两个值一样可以只写一个。

命名区域

我们可以为每个格子命名,相同命名的格子则为一个整体,然后可以利用grid-area: 命名;的形式,将元素快速定位到对应的格子中,且此时的排列顺序就不会根据dom顺序排列,而是grid自动排序,如果有空隙,会将后面的元素移动到空隙部分,如果能放下的话。

.box {
    height: 100vh;
    display: grid;
    grid-template-columns: repeat(3, 20%) auto;
    grid-template-rows: 50px 100px;
    grid-gap: 20px 20px;
    grid-template-areas: "header header sidebar sidebar" 
                         "main main footer footer";
}

.item1 {
    background-color: blanchedalmond;
    grid-area: header;
}

.item2 {
    background-color: aquamarine;
    grid-area: sidebar;
}

.item3 {
    background-color: burlywood;
    grid-area: main;
}

.item4 {
    background-color: darkcyan;
    grid-area: footer;
}

.item5 {
    background-color: darksalmon;
}

grid-template-areas配置格子命名,每行用引号包裹,可以单引号或者双引号,如果不想命名,可以用.代替。

grid-template-areas: "header header sidebar sidebar" 
                     ". . footer footer";

使用时,给子元素配置命名即可:grid-area: footer;

如果使用了不存在的命名,格子就会发生变化和错乱。

注意: 如果我们配置了name,就可以勾选浏览器的显示name选项,可以很方便的看到每个格子的名称,这种方式可以很方便的进行布局使用。

自动推断网格命名

这个功能可能用的比较少,而且设置上比较繁琐,估计不会有很多人这么用。

grid支持自动推断网格名称,前提是网格线的命名必须要以:xxx-start、xxx-end这种命名方式,且xxx必须是相同的名字。

.box {
    height: 100vh;
    display: grid;
    grid-template-columns: [hd-start] repeat(3, 20%) auto [hd-end];
    grid-template-rows: [hd-start] 50px [hd-end] 100px;
    grid-gap: 20px 20px;
}

我们给四个格子都在hd的范围,然后第一行也是hd;那么我们使用时就可以将hd作为一个网格命名来使用

.item1 {
    background-color: blanchedalmond;
    grid-area: hd;
}

子元素水平对齐

grid也和flex一样控制子元素的水平对齐方式。但是控制的是元素所在格子范围内的水平对齐

.box {
    height: 100vh;
    display: grid;
    grid-template-columns: repeat(5, calc(20% - 20px));
    grid-template-rows: 100px;
    grid-gap: 20px;
    justify-items: center;
}

justify-items的属性有:

  • stretch 默认效果
  • center 水平居中对齐
  • start 水平起始点对齐
  • end 水平结尾对齐
  • 更多自己查文档

除了stretch,其他的对齐都会使得子元素默认占满格子宽度的效果失效。可以给子元素添加wdith:100%来占满宽度。

注意: start和end不等同于left和right,它们会跟随文档的阅读方向改变而改变,默认是从左到右,有的国家是从右到左

子元素垂直对齐

控制的是元素所在格子范围内的垂直对齐

.box {
    height: 100vh;
    display: grid;
    grid-template-columns: repeat(5, calc(20% - 20px));
    grid-template-rows: 100px;
    grid-gap: 20px;
    align-items: center;
}

align-items的属性有:

  • stretch 默认效果
  • center 垂直居中对齐
  • start 垂直起始点对齐
  • end 垂直结尾对齐
  • 更多自己查文档

整体内容水平对齐

这个就是控制整个元素在grid中的水平对齐方式。

.box {
    height: 100vh;
    display: grid;
    grid-template-columns: repeat(7, 100px);
    grid-template-rows: 100px;
    grid-gap: 20px;
    justify-content: center;
}

justify-content的属性有:

  • stretch 默认效果
  • center 水平居中对齐
  • start 水平起始点对齐
  • end 水平结尾对齐
  • 更多自己查文档

整体垂直对齐

这个就是控制整个元素在grid中的垂直对齐方式。

.box {
    height: 100vh;
    display: grid;
    grid-template-columns: repeat(7, 100px);
    grid-template-rows: 100px;
    grid-gap: 20px;
    align-content: center;
}

align-content的属性有:

  • stretch 默认效果
  • center 垂直居中对齐
  • start 垂直起始点对齐
  • end 垂直结尾对齐
  • 更多自己查文档

单独控制子元素自己再格子内的对齐方式

这点和flex的有些相同的,但是grid的只能控制元素在格子范围内的对齐方式。

.box {
    height: 100vh;
    display: grid;
    grid-template-columns: repeat(7, 100px);
    grid-template-rows: 100px;
    grid-gap: 20px;
    align-content: center;
    justify-content: center;
}

.item2 {
    background-color: aquamarine;
    justify-self: start;
    align-self: start;
}

justify-selfalign-self的值都上面那些一样,具体也可以自己去查文档。

媒体查询的响应式处理

格子的大小数量都是定死的,如果随着设备的变化,pc端到移动端,宽度会越来越小,如果我们想让某些格子发生响应式变化,就需要重新增删格子的配置。

.box {
    height: 100vh;
    display: grid;
    grid-template-columns: repeat(4, 100px);
    grid-template-rows: 100px 200px;
    grid-gap: 20px;
    grid-template-areas: "header header header header"
                         "sidebar sidebar main main";
}

@media (max-width: 768px) {
    .box {
        grid-template-rows: 100px 100px 200px;
        grid-template-areas: "header header header header"
                             "sidebar sidebar sidebar sidebar"
                             "main main main main";
    }
}

这里以自定义命名区域为例,通过响应式调整命名区域和row数量,子元素对应使用的命名区域定位,响应式触发时,元素位置也会发生变化。

控制grid自动添加格子的默认行为

当我们新增的元素已经超出格子的数量时,他会自动生成新的一行,并且每行的高度在没有配置的情况,以内容高度最高的那个格子为基准,这点和table效果是一样的。

我们可以控制自动生成的每行高度。

.box {
    height: 100vh;
    display: grid;
    grid-template-columns: repeat(4, 100px);
    grid-template-rows: 100px 200px;
    grid-gap: 20px;
    grid-auto-rows: 100px;  /*控制自动生成每行的高度*/
}

控制自动生成为列

默认情况下超出控制的元素会自动生成的row来包裹,但是我们可以控制它的行为。

.box {
    height: 100vh;
    display: grid;
    grid-template-columns: repeat(4, 100px);
    grid-template-rows: 100px 200px;
    grid-gap: 20px;
    grid-auto-flow: column;  /*控制自动生成列*/
}

这样设置元素就不会往下排列,而是往右边生成列了。

控制自动生成列的宽度

.box {
    height: 100vh;
    display: grid;
    grid-template-columns: repeat(4, 100px);
    grid-template-rows: 100px 200px;
    grid-gap: 20px;
    grid-auto-flow: column;  /*控制自动生成列*/
    grid-auto-columns: 100px;
}

简单布局原理总结

从以上的css配置来看,我们可以明确的知道,格子是有两种配置的,一种是显式配置,也就是通过grid-template-columnsgrid-template-rows显式声明格子数量大小的,一种是隐式配置,他会将超出配置的元素安排在自动生成的格子配置上,虽然这个配置我们也可以插手进行修改。

但是这个很重要,这对于我们记住grid的布局原理很有帮助。

自动换行

比较常见的一个功能,但是grid默认配置是定死的,但是我们希望的时,在一个固定格子大小的情况下,格子能根据页面的大小自动排列换行。

.box {
    height: 100vh;
    display: grid;
    grid-template-columns: repeat(auto-fill, 300px);
    grid-template-rows: 100px 200px;
    justify-content: center;
}

auto-fill的作用是让元素尽可能的占满一行,且列的宽度都是300px

可以看到当一行宽度不够时,元素会自动换行,并且是左对齐状态(水平对齐失效)。

我们还可以使用auto-fit;该属性效果等同于auto-fill;但是auto-fill会导致justify-content对齐失效,而使用auto-fit;会在换行时保留justify-content的效果。

.box {
    height: 100vh;
    display: grid;
    grid-template-columns: repeat(auto-fit, 300px);
    grid-template-rows: 100px 200px;
    justify-content: center;
}

空白行为

当一行的格子不能满足某一个格子的宽度要求时,这个格子会被自动换行。但是上一行空出的位置,不会有元素去占据。

.box {
    width: 900px;
    height: 100vh;
    display: grid;
    grid-template-columns: repeat(3, 300px);
    grid-template-rows: 100px 200px;
}

.item1 {
    background-color: blanchedalmond;
    grid-column: span 2;
}

.item2 {
    background-color: aquamarine;
    grid-column: span 2;
}

css中我们设置每行有3个格子,但是item1和item2都要占据两个格子,这就导致第一行格子数量不满足需要,item2被换行处理了。

有啥办法可以让这个空白占满呢?

答案是有的,我们可以控制自动生成row时的行为,利用grid-auto-flow配置。

.box {
    width: 900px;
    height: 100vh;
    display: grid;
    grid-template-columns: repeat(3, 300px);
    grid-template-rows: 100px 200px;
    grid-auto-flow: row dense;
}

grid-auto-flow默认值是row,后面接dense表示改变跳过空白的这种行为,这就可以让后面的格子去占据空白的部分。

当然column也可以加这个属性。

grid-auto-flow: column dense;

注意:

虽然我们可以控制这个空白的行为,但是并不建议这么做,因为这会导致正常用户与无障碍用户产生阅读上的问题。

正常用户看到的元素顺序是:1、3、2、4、5

而无障碍用户它的阅读顺序是根据dom顺序来阅读的:1、2、3、4、5

结语

至此grid的布局基本结束,我们需要考虑的是grid与flex布局,它的合理使用。

如果一个布局,我们只需要考虑单向的排列布局,那么flex更加合适,而grid适合更加复杂的情况,比如ui框架中的row布局,其实用grid会更加便捷。

分类: CSS 标签: cssgrid

评论

暂无评论数据

暂无评论数据

目录