CSS Grid(二维网格)布局,比Flex更灵活

2023-06-1406:55:35网页制作Comments867 views字数 6986阅读模式

CSS Grid布局也叫二维网格布局系统,可用于布局页面主要的区域布局或小型组件。网格是一组相交的水平线和垂直线,它定义了网格的列和行。我们可以指定将网格元素放置在与这些行和列相关的位置上。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/zhizuo/46953.html

一维布局 和 二维布局

像流布局和Flex布局,他们都是一维布局。一维布局一次只能处理一个维度上的元素布局,一行或者一列。回想一下,流布局和Flex布局的兄弟节点,是不是都是按照行或者列来显示的。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/zhizuo/46953.html

网格布局是二维布局,可以同时处理行和列上的布局。使用网格布局,兄弟节点可以被指定布局到网格的某个位置。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/zhizuo/46953.html

所以,网格布局相对流布局Flex布局更加的灵活,当然学习和使用也更加复杂。这篇文章会把网格布局中的概念和属性整理出来。如果觉得有用,还请点赞收藏。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/zhizuo/46953.html

下图就是展示了一维布局和二维布局的不同。可以看出,如果布局复杂,一维布局需要增加节点来解决;而二维布局,则不需要,这也是网格布局强大而复杂的原因。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/zhizuo/46953.html

CSS Grid(二维网格)布局,比Flex更灵活

Grid布局中的概念

网格容器

我们通过在元素上声明 display:grid 或 display:inline-grid 来创建一个网格容器。一旦我们这样做,这个元素的所有直系子元素将成为网格元素。网格容器的设置和flex容器的设置类似。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/zhizuo/46953.html

在网格容器节点行,我们可以通过grid-template-columnsgrid-template-rows指定当前容器的行和列。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/zhizuo/46953.html

如下面的代码,就会生成一个2行3列的效果。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/zhizuo/46953.html

1<div class="grid-box-1">
2  <div>1</div>
3  <div>2</div>
4  <div>3</div>
5  <div>4</div>
6  <div>5</div>
7</div>

 1.grid-box-1 {
 2  border: 1px solid #999;
 3  width: 300px;
 4  height: 200px;
 5  display: grid;
 6  margin: 20px;
 7  grid-template-columns: 1fr 1fr 1fr;  /* 指定 3 列*/
 8  grid-template-rows: 1fr 1fr; /* 指定 2行 */
 9}
10.grid-box-1 > div {
11  background-color: bisque;
12  border-radius: 4px;
13  border: 1px solid #ccc;
14}
CSS Grid(二维网格)布局,比Flex更灵活

网格轨道

通过grid-template-columnsgrid-template-rows指定当前容器的行和列后,这里的行和列就是网格轨道。但在实际页面中,由于页面的内容不确定,内容可能会超过grid-template-columnsgrid-template-rows指定的网格轨道个数,这个时候网格将会在隐式网格中创建行和列。按照默认,这些轨道将自动定义尺寸,所以会根据它里面的内容改变尺寸。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/zhizuo/46953.html

你也可以在隐式网格中用 grid-auto-rows 和 grid-auto-columns 属性来定义一个设置大小尺寸的轨道。还是拿上面的例子,如果Grid的子节点大于6个,就会出现隐式网格。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/zhizuo/46953.html

 1<div class="grid-box-2">
 2  <div>1</div>
 3  <div>2</div>
 4  <div>3</div>
 5  <div>4</div>
 6  <div>5</div>
 7  <div>6</div>
 8  <div>7</div>
 9  <div>8</div>
10  <div>9</div>
11  <div>10</div>
12  <div>11</div>
13</div>

 1/* 隐式网格 */
 2.grid-box-2 {
 3  border: 1px solid #999;
 4  width: 300px;
 5  height: 200px;
 6  display: grid;
 7  margin: 20px;
 8  grid-template-columns: 1fr 1fr 1fr;
 9  grid-template-rows: 1fr 1fr;
10}
11.grid-box-2 > div {
12  background-color: bisque;
13  border-radius: 4px;
14  border: 1px solid #ccc;
15}
CSS Grid(二维网格)布局,比Flex更灵活

上面的代码中,如果Grid的子节点超过了6个,父节点的高度是200,那么超出指定网格轨道的子节点就是隐式网格,隐式网格不会根据网格轨道的样式来进行设置。比如例子中就是,隐式网格的高度是内容的高度,父节点剩余的空间会分配给两个指定的网格轨道,轨道1:1比例分配。
当然,我们也可以设置隐式网格的样式,通过grid-auto-rowsgrid-auto-columns可以对隐式网格的行列进行设置。如下面的例子,设置了隐式网格轨道的行高为40,那么显示网格高度就是60((200-40*2) / 2)。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/zhizuo/46953.html

1.grid-box-2 {
2  grid-auto-rows: 40px; /* 添加隐式网格的行高30px */
3}
CSS Grid(二维网格)布局,比Flex更灵活

网格线

设置网格轨道时,Grid会为我们创建带编号的网格线来让我们来定位每一个网格元素。还是拿上面的代码做例子,他的网格线编号会是下图中的顺序(负数表示从后往前的编号,不含隐式网格对应的网格线)。注意:网格线的编号顺序取决于文章的书写模式。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/zhizuo/46953.html

CSS Grid(二维网格)布局,比Flex更灵活

有了网格线,我们可以通过网格线指定跨轨道的网格元素,从而实现网格元素占多行多列的效果。子元素通过grid-column-startgrid-column-endgrid-row-startgrid-row-end或者grid-columngrid-row,或者通过grid-area这一个属性来设置来指定元素占据的网格轨道。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/zhizuo/46953.html

这里的属性值不仅可以指定网格线,还可以指定span xx 这个的意思是占据多少网格轨道。这个更符合我们的思维习惯。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/zhizuo/46953.html

这里有7个属性,其实很好记忆,占据空间是通过指定网格线来指定的,所以会有行列 + 开始结束,这里是4个属性。然后行列的开始结束分别提供一个缩写,这里就是2个属性。最后,可以通过grid-area一个属性指定行列。
grid-area的顺序是row-start / column-start / row-end / column-end。可以通过从左往右,从上往下,先startend来记忆。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/zhizuo/46953.html

 1.grid-box-3 > div:nth-of-type(1) {
 2  grid-column-start: 1;
 3  grid-column-end: 4;
 4  grid-row-start: 1;
 5  grid-row-end: 2; /* 如果只占一行或一列,grid-xx-end属性可以不用写 */
 6
 7  /* 等同于下面的代码 */
 8  grid-area: 1 / 1 / 2 / 4;  /* 这里的顺序是:row-start / column-start / row-end / column-end */ 
 9}
10.grid-box-3 > div:nth-of-type(2) {
11  grid-row: 2 / 4; /* grid-row 是 grid-row-start 和 grid-row-end的缩写 */
12}
13.grid-box-3 > div:nth-of-type(3) {
14  grid-column: 2 / span 2; /* span表示占据几行,这里表示从2开始,占据2行,也就是网格线2到4 */
15}
16.grid-box-3 > div:nth-of-type(6) {
17  grid-column: 1 / span 3;
18}
CSS Grid(二维网格)布局,比Flex更灵活

网格单元和网格间距

一个网格单元是在一个网格元素中最小的单位,比如上面的例子中,4行3列,那么网格布局的父元素就被划分成4*3=12个网格单元,子级元素将会排列在每个事先定义好的网格单元中。网格元素可以向行或着列的方向扩展一个或多个单元,并且会创建一个网格区域。网格区域的形状应该是一个矩形(也就是说你不可能创建出一个类似于“L”形的网格区域)。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/zhizuo/46953.html

网格单元之间可以通过grid-column-gapgrid-row-gap或者grid-gap设置网格间距。下面的例子就是把网格列间距设置为2px,网格行间距设置为6px。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/zhizuo/46953.html

现在好像是改成column-gaprow-gap和 gap了。gap的顺序是row-gap column-gap文章源自菜鸟学院-https://www.cainiaoxueyuan.com/zhizuo/46953.html

1.grid-box-4 {
2  /* 等同于 gap: 6px 2px; */
3  grid-column-gap: 2px;
4  grid-row-gap: 6px;
5}
CSS Grid(二维网格)布局,比Flex更灵活

Grid布局细节

使用`repeat`设置行列

我们再设置行列时,会遇到很多列的情况,如果一列一列去指定,太麻烦了。这个时候我们可以通过repeat函数来设置。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/zhizuo/46953.html

1.grid-box-6 {
2  /* 等同于 grid-template-columns: 1fr 1fr 1fr; */
3    grid-template-columns: repeat(3, 1fr);
4}

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

有的时候,父容器的尺寸是不确定的,我们需要把子元素往父容器中逐个填充,这个时候我们可以利用auto-fillgrid-template-columns: repeat(auto-fill, 50px);表示,每一列都是50px,但是具体有几列,需要根据子元素填充的情况来定。能放下8列,就放8列,不够9列的部分空白。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/zhizuo/46953.html

 1/* Grid 容器尺寸不固定,自动适配子元素 */
 2.grid-box-6 {
 3  border: 1px solid #999;
 4  display: grid;
 5  margin: 20px;
 6  grid-template-columns: repeat(auto-fill, 50px);
 7}
 8.grid-box-6 > div {
 9  height: 50px;
10  background-color: bisque;
11  border-radius: 4px;
12  border: 1px solid #ccc;
13}
CSS Grid(二维网格)布局,比Flex更灵活

如果不希望后面有空白呢,这个时候就需要子节点有适当的宽度适配。子节点不再是固定宽度,而是通过minmax函数指定最小值。如果容器的行不够整数,那么就按照1:1的比例去适当增宽子节点。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/zhizuo/46953.html

1.grid-box-6 {
2  grid-template-columns: repeat(auto-fill, minmax(50px, 1fr)) ;
3}
CSS Grid(二维网格)布局,比Flex更灵活

网格项目重叠

上面讲到,每一个网格项目都可以指定占据的网格单元。如果多个网格项目占据同一个网格单元呢。比如上面的例子,网格项目1和网格项目2都需要占据左上角这个网格单元。效果会是下面这样:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/zhizuo/46953.html

CSS Grid(二维网格)布局,比Flex更灵活

我们会发现是2盖住了1, 按照先后顺序,默认情况是后面的DOM节点盖住前面的DOM节点。不过我们可以通过设置z-index来改变覆盖顺序。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/zhizuo/46953.html

1.grid-box-5 > div:nth-of-type(1) {
2  z-index: 2;
3}
CSS Grid(二维网格)布局,比Flex更灵活

网格线的命名

虽然我们可以通过指定网格线来确定网格区域,但是网格线还是太不直观了。接下来我们讲一讲怎么通过对网格线命名来解决这个问题。使用Chrome Dev Tools布局查看,可以看到命名的网格线名字。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/zhizuo/46953.html

 1.grid-box-7 {
 2  grid-template-columns: [main-start] 1fr [content-start] 1fr [content-end] 1fr [main-end];
 3  grid-template-rows: [main-start] 40px [content-start] 40px [content-end] 40px [main-end];
 4}
 5.grid-box-7 > div:nth-of-type(1) {
 6  grid-column-start: main-start;
 7  grid-column-end: main-end;
 8  grid-row-start: main-start;
 9  grid-row-end: content-start;
10}
11.grid-box-7 > div:nth-of-type(2) {
12  grid-column: main-start / content-start;
13  grid-row: content-start / main-end;
14}
CSS Grid(二维网格)布局,比Flex更灵活

网格模板区域

虽然可以指定网格线的名字,但是网格线用起来还是不够方便,Grid布局提供了一个模板区域的设置方法。
网格项目中的属性grid-area会指定当前网格项目的名字,在网格容器中的属性grid-template-areas会通过参数中的名字, 设置对应网格项目的位置和所占空间,其中.表示1fr的空白。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/zhizuo/46953.html

 1.grid-box-8 {
 2  border: 1px solid #999;
 3  width: 400px;
 4  height: 120px;
 5  margin: 20px;
 6  display: grid;
 7  grid-template-columns: repeat(9, 1fr);
 8  grid-template-areas:
 9    "hd hd hd hd hd hd hd hd hd"
10    "sd sd sd main main main main . ."
11    "sd sd sd ft ft ft ft ft ft";
12}
13.grid-box-8 > div {
14  background-color: bisque;
15  border-radius: 4px;
16  border: 1px solid #ccc;
17}
18.grid-box-8 > div:nth-of-type(1){
19  grid-area: hd;
20}
21.grid-box-8 > div:nth-of-type(2){
22  grid-area: ft;
23}
24.grid-box-8 > div:nth-of-type(3) {
25  grid-area: main;
26}
27.grid-box-8 > div:nth-of-type(4) {
28  grid-area: sd;
29}
CSS Grid(二维网格)布局,比Flex更灵活

填充缺口

有的场景下,由于子元素宽度的不确定性,会出现空格,前面通过了grid-template-columns: repeat(auto-fill, minmax(50px, 1fr))解决了部分情况。但是如果网格项目的宽度是不变的,但是顺序可变。这个时候,我们就可以通过grid-auto-flow来解决。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/zhizuo/46953.html

grid-auto-flow是控制自动布局算法怎样运作的属性,它能精确指定在网格中被自动布局的元素怎样排列。它有3个属性值:column``,row(默认),dense。可以看出来,如果是columns网格项目就是先把一列排满,再填如第二列。row就是先填满一行,因为这个是默认值,所以前面的例子都是先填满一行,再填下一行。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/zhizuo/46953.html

那这里的dense呢,它指定自动布局算法使用一种“稠密”堆积算法,如果后面出现了稍小的元素,则会试图去填充网格中前面留下的空白。这样做会填上稍大元素留下的空白,但同时也可能导致原来出现的次序被打乱。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/zhizuo/46953.html

这样我们就可以利用grid-auto-flow: dense来解决空白问题。(不能完美解决,只能让空白变小。)文章源自菜鸟学院-https://www.cainiaoxueyuan.com/zhizuo/46953.html

比如下面这个例子,第一个子节点占了三列,第二个子节点占了2列,那么第一行就会空一个。添加了grid-auto-flow: row dense后,就能自动匹配能填充到这个空间的子节点。(grid-auto-flow: dense也是同样的效果)文章源自菜鸟学院-https://www.cainiaoxueyuan.com/zhizuo/46953.html

 1.grid-box-9 {
 2  width: 200px;
 3  display: grid;
 4  gap: 2px;
 5  grid-template-columns: repeat(4, 1fr);
 6  grid-auto-rows: 50px;
 7  /* grid-auto-flow: row dense; */
 8}
 9.grid-box-9 > div:nth-of-type(1){
10  grid-column-end: span 3;
11}
12.grid-box-9 > div:nth-of-type(2n){
13  grid-column-end: span 2;
14  grid-row-end: span 2;
15}
CSS Grid(二维网格)布局,比Flex更灵活
CSS Grid(二维网格)布局,比Flex更灵活

元素的对齐

和flex类似,Grid布局有以下容器属性用于对齐:justify-contentjustify-itemalign-contentalign-item,另外,Grid还增加了place-content和 place-item用于缩写。子元素也有三个用于对齐属性:justify-selfalign-selfplace-self文章源自菜鸟学院-https://www.cainiaoxueyuan.com/zhizuo/46953.html

简单记忆:justify是在垂直方向对齐方式,align是水平方向对齐对齐,place是前面两个属性的缩写,先alignjustifycontent是容器子元素的对齐,item是子元素所在自己空间的对齐;self是子元素的属性,用于覆盖父容器对应的item样式。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/zhizuo/46953.html

justify-items: 垂直方向(列维度)的子元素在自己空间的对齐

CSS Grid(二维网格)布局,比Flex更灵活
CSS Grid(二维网格)布局,比Flex更灵活
CSS Grid(二维网格)布局,比Flex更灵活
CSS Grid(二维网格)布局,比Flex更灵活

align-items: 水平方向(行维度)的子元素在自己空间的对齐

CSS Grid(二维网格)布局,比Flex更灵活
CSS Grid(二维网格)布局,比Flex更灵活
CSS Grid(二维网格)布局,比Flex更灵活
CSS Grid(二维网格)布局,比Flex更灵活
CSS Grid(二维网格)布局,比Flex更灵活

justify-content: 垂直方向上,子元素在容器空间中的对齐

CSS Grid(二维网格)布局,比Flex更灵活
CSS Grid(二维网格)布局,比Flex更灵活
CSS Grid(二维网格)布局,比Flex更灵活
CSS Grid(二维网格)布局,比Flex更灵活
CSS Grid(二维网格)布局,比Flex更灵活
CSS Grid(二维网格)布局,比Flex更灵活
CSS Grid(二维网格)布局,比Flex更灵活

align-content: 水平方向上,子元素在容器空间中的对齐

CSS Grid(二维网格)布局,比Flex更灵活
CSS Grid(二维网格)布局,比Flex更灵活
CSS Grid(二维网格)布局,比Flex更灵活
CSS Grid(二维网格)布局,比Flex更灵活
CSS Grid(二维网格)布局,比Flex更灵活
CSS Grid(二维网格)布局,比Flex更灵活
CSS Grid(二维网格)布局,比Flex更灵活

justify-self 和 align-self

justify-self:子元素属性,垂直方向上的对齐方式,覆盖父元素中justify-items的值。具体的值和效果,同justify-items文章源自菜鸟学院-https://www.cainiaoxueyuan.com/zhizuo/46953.html

align-self: 子元素属性,水平方向上的对齐方式,覆盖父元素中align-items的值。具体的值和效果,同align-items文章源自菜鸟学院-https://www.cainiaoxueyuan.com/zhizuo/46953.html

  • 本站内容整理自互联网,仅提供信息存储空间服务,以方便学习之用。如对文章、图片、字体等版权有疑问,请在下方留言,管理员看到后,将第一时间进行处理。
  • 转载请务必保留本文链接:https://www.cainiaoxueyuan.com/zhizuo/46953.html

Comment

匿名网友 填写信息

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定