关于前端:熟练了Flex布局之后该学学Grid布局了

5次阅读

共计 10319 个字符,预计需要花费 26 分钟才能阅读完成。

Grid 的内容有点多,这一篇整顿了概念和属性,算是“实践”篇,前面会再写一篇 Grid 的例子,当作“实际”篇。如果感觉学了不晓得用在哪里的,能够关注下。

介绍

CSS Gird 布局也叫 二维网格布局零碎,可用于布局页面次要的区域布局或小型组件。网格是一组相交的水平线和垂直线,它定义了网格的列和行。咱们能够指定将网格元素搁置在与这些行和列相干的地位上。

一维布局 和 二维布局

像流布局和 Flex 布局,他们都是一维布局。一维布局一次只能解决一个维度上的元素布局,一行或者一列。回忆一下,流布局和 Flex 布局的兄弟节点,是不是都是依照行或者列来显示的。

网格布局是二维布局,能够同时解决行和列上的布局。应用网格布局,兄弟节点能够被指定布局到网格的某个地位。

所以,网格布局绝对流布局 Flex 布局更加的灵便,当然学习和应用也更加简单。这篇文章会把网格布局中的概念和属性整理出来。如果感觉有用,还请点赞珍藏。

下图就是展现了一维布局和二维布局的不同。能够看出,如果布局简单,一维布局须要减少节点来解决;而二维布局,则不须要,这也是网格布局弱小而简单的起因。

Grid 布局中的概念

网格容器

咱们通过在元素上申明 display:griddisplay:inline-grid 来创立一个网格容器。一旦咱们这样做,这个元素的所有直系子元素将成为网格元素。网格容器的设置和 flex 容器的设置相似。

在网格容器节点行,咱们能够通过 grid-template-columnsgrid-template-rows指定以后容器的行和列。

如上面的代码,就会生成一个 2 行 3 列的成果。

<div class="grid-box-1">
  <div>1</div>
  <div>2</div>
  <div>3</div>
  <div>4</div>
  <div>5</div>
</div>
.grid-box-1 {
  border: 1px solid #999;
  width: 300px;
  height: 200px;
  display: grid;
  margin: 20px;
  grid-template-columns: 1fr 1fr 1fr;  /* 指定 3 列 */
  grid-template-rows: 1fr 1fr; /* 指定 2 行 */
}
.grid-box-1 > div {
  background-color: bisque;
  border-radius: 4px;
  border: 1px solid #ccc;
}

网格轨道

通过 grid-template-columnsgrid-template-rows指定以后容器的行和列后,这里的行和列就是网格轨道。但在理论页面中,因为页面的内容不确定,内容可能会超过 grid-template-columnsgrid-template-rows指定的网格轨道个数,这个时候网格将会在隐式网格中创立行和列。依照默认,这些轨道将主动定义尺寸,所以会依据它外面的内容扭转尺寸。

你也能够在隐式网格中用 grid-auto-rowsgrid-auto-columns 属性来定义一个设置大小尺寸的轨道。
还是拿下面的例子,如果 Grid 的子节点大于 6 个,就会呈现隐式网格。

<div class="grid-box-2">
  <div>1</div>
  <div>2</div>
  <div>3</div>
  <div>4</div>
  <div>5</div>
  <div>6</div>
  <div>7</div>
  <div>8</div>
  <div>9</div>
  <div>10</div>
  <div>11</div>
</div>
/* 隐式网格 */
.grid-box-2 {
  border: 1px solid #999;
  width: 300px;
  height: 200px;
  display: grid;
  margin: 20px;
  grid-template-columns: 1fr 1fr 1fr;
  grid-template-rows: 1fr 1fr;
}
.grid-box-2 > div {
  background-color: bisque;
  border-radius: 4px;
  border: 1px solid #ccc;
}

下面的代码中,如果 Grid 的子节点超过了 6 个,父节点的高度是 200,那么超出指定网格轨道的子节点就是隐式网格,隐式网格不会依据网格轨道的款式来进行设置。比方例子中就是,隐式网格的高度是内容的高度,父节点残余的空间会调配给两个指定的网格轨道,轨道 1:1 比例调配。
当然,咱们也能够设置隐式网格的款式,通过 grid-auto-rowsgrid-auto-columns能够对隐式网格的行列进行设置。如上面的例子,设置了隐式网格轨道的行高为 40,那么显示网格高度就是 60((200-40*2) / 2)。

.grid-box-2 {grid-auto-rows: 40px; /* 增加隐式网格的行高 30px */}

网格线

设置网格轨道时,Grid 会为咱们创立带编号的网格线来让咱们来定位每一个网格元素。还是拿下面的代码做例子,他的网格线编号会是下图中的程序(正数示意从后往前的编号,不含隐式网格对应的网格线)。留神:网格线的编号程序取决于文章的书写模式。

有了网格线,咱们能够通过网格线指定跨轨道的网格元素,从而实现网格元素占多行多列的成果。子元素通过 grid-column-startgrid-column-endgrid-row-startgrid-row-end 或者 grid-columngrid-row,或者通过 grid-area 这一个属性来设置来指定元素占据的网格轨道。

这里的属性值不仅能够指定网格线,还能够指定span xx 这个的意思是占据多少网格轨道。这个更合乎咱们的思维习惯。

这里有 7 个属性,其实很好记忆,占据空间是通过指定网格线来指定的,所以会有行列 + 开始完结,这里是 4 个属性。而后行列的开始完结别离提供一个缩写,这里就是 2 个属性。最初,能够通过 grid-area 一个属性指定行列。
grid-area的程序是 row-start / column-start / row-end / column-end。能够通过从左往右,从上往下,先startend来记忆。

.grid-box-3 > div:nth-of-type(1) {
  grid-column-start: 1;
  grid-column-end: 4;
  grid-row-start: 1;
  grid-row-end: 2; /* 如果只占一行或一列,grid-xx-end 属性能够不必写 */

  /* 等同于上面的代码 */
  grid-area: 1 / 1 / 2 / 4;  /* 这里的程序是:row-start / column-start / row-end / column-end */ 
}
.grid-box-3 > div:nth-of-type(2) {grid-row: 2 / 4; /* grid-row 是 grid-row-start 和 grid-row-end 的缩写 */}
.grid-box-3 > div:nth-of-type(3) {grid-column: 2 / span 2; /* span 示意占据几行,这里示意从 2 开始,占据 2 行,也就是网格线 2 到 4 */}
.grid-box-3 > div:nth-of-type(6) {grid-column: 1 / span 3;}

网格单元和网格间距

一个网格单元是在一个网格元素中最小的单位,比方下面的例子中,4 行 3 列,那么网格布局的父元素就被划分成 4 *3=12 个网格单元,子级元素将会排列在每个当时定义好的网格单元中。网格元素能够向行或着列的方向扩大一个或多个单元,并且会创立一个网格区域。网格区域的形态应该是一个矩形(也就是说你不可能创立出一个相似于“L”形的网格区域)。

网格单元之间能够通过 grid-column-gapgrid-row-gap 或者 grid-gap 设置网格间距。上面的例子就是把网格列间距设置为 2px,网格行间距设置为 6px。

当初如同是改成 column-gaprow-gapgap了。gap的程序是row-gap column-gap

.grid-box-4 {
  /* 等同于 gap: 6px 2px; */
  grid-column-gap: 2px;
  grid-row-gap: 6px;
}

Grid 布局细节

应用 repeat 设置行列

咱们再设置行列时,会遇到很多列的状况,如果一列一列去指定,太麻烦了。这个时候咱们能够通过 repeat 函数来设置。

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

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

有的时候,父容器的尺寸是不确定的,咱们须要把子元素往父容器中一一填充,这个时候咱们能够利用 auto-fillgrid-template-columns: repeat(auto-fill, 50px); 示意,每一列都是 50px,然而具体有几列,须要依据子元素填充的状况来定。能放下 8 列,就放 8 列,不够 9 列的局部空白。

/* Grid 容器尺寸不固定,主动适配子元素 */
.grid-box-6 {
  border: 1px solid #999;
  display: grid;
  margin: 20px;
  grid-template-columns: repeat(auto-fill, 50px);
}
.grid-box-6 > div {
  height: 50px;
  background-color: bisque;
  border-radius: 4px;
  border: 1px solid #ccc;
}

如果不心愿前面有空白呢,这个时候就须要子节点有适当的宽度适配。子节点不再是固定宽度,而是通过 minmax 函数指定最小值。如果容器的行不够整数,那么就依照 1:1 的比例去适当增宽子节点。

.grid-box-6 {grid-template-columns: repeat(auto-fill, minmax(50px, 1fr)) ;
}

网格我的项目重叠

下面讲到,每一个网格我的项目都能够指定占据的网格单元。如果多个网格我的项目占据同一个网格单元呢。比方下面的例子,网格我的项目 1 和网格我的项目 2 都须要占据左上角这个网格单元。成果会是上面这样:

咱们会发现是 2 盖住了 1,依照先后顺序,默认状况是前面的 DOM 节点盖住后面的 DOM 节点。不过咱们能够通过设置 z-index 来扭转笼罩程序。

.grid-box-5 > div:nth-of-type(1) {z-index: 2;}

网格线的命名

尽管咱们能够通过指定网格线来确定网格区域,然而网格线还是太不直观了。接下来咱们讲一讲怎么通过对网格线命名来解决这个问题。应用 Chrome Dev Tools 布局查看,能够看到命名的网格线名字。

.grid-box-7 {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-7 > 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-7 > div:nth-of-type(2) {
  grid-column: main-start / content-start;
  grid-row: content-start / main-end;
}

网格模板区域

尽管能够指定网格线的名字,然而网格线用起来还是不够不便,Grid 布局提供了一个模板区域的设置办法。
网格我的项目中的属性 grid-area 会指定以后网格我的项目的名字,在网格容器中的属性 grid-template-areas 会通过参数中的名字,设置对应网格我的项目的地位和所占空间,其中. 示意 1fr 的空白。

.grid-box-8 {
  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-8 > div {
  background-color: bisque;
  border-radius: 4px;
  border: 1px solid #ccc;
}
.grid-box-8 > div:nth-of-type(1){grid-area: hd;}
.grid-box-8 > div:nth-of-type(2){grid-area: ft;}
.grid-box-8 > div:nth-of-type(3) {grid-area: main;}
.grid-box-8 > div:nth-of-type(4) {grid-area: sd;}

填充缺口

有的场景下,因为子元素宽度的不确定性,会呈现空格,后面通过了 grid-template-columns: repeat(auto-fill, minmax(50px, 1fr)) 解决了局部状况。然而如果网格我的项目的宽度是不变的,然而程序可变。这个时候,咱们就能够通过 grid-auto-flow 来解决。

grid-auto-flow是管制主动布局算法怎么运作的属性,它能准确指定在网格中被主动布局的元素怎么排列。它有 3 个属性值:column`,row(默认),dense。能够看进去,如果是 columns 网格我的项目就是先把一列排满,再填如第二列。row` 就是先填满一行,因为这个是默认值,所以后面的例子都是先填满一行,再填下一行。

那这里的 dense 呢,它指定主动布局算法应用一种“浓密”沉积算法,如果前面呈现了稍小的元素,则会试图去填充网格中后面留下的空白。这样做会填上稍大元素留下的空白,但同时也可能导致原来呈现的秩序被打乱。

这样咱们就能够利用 grid-auto-flow: dense 来解决空白问题。(不能完满解决,只能让空白变小。)

比方上面这个例子,第一个子节点占了三列,第二个子节点占了 2 列,那么第一行就会空一个。增加了 grid-auto-flow: row dense 后,就能主动匹配能填充到这个空间的子节点。(grid-auto-flow: dense也是同样的成果)

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

元素的对齐

和 flex 相似,Grid 布局有以下容器属性用于对齐:justify-contentjustify-itemalign-contentalign-item,另外,Grid 还减少了 place-contentplace-item用于缩写。子元素也有三个用于对齐属性:justify-selfalign-selfplace-self

简略记忆:justify是在垂直方向对齐形式,align是程度方向对齐对齐,place是后面两个属性的缩写,先 alignjustifycontent是容器子元素的对齐,item是子元素所在本人空间的对齐;self是子元素的属性,用于笼罩父容器对应的 item 款式。

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

align-items: 程度方向 (行维度) 的子元素在本人空间的对齐

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

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

justify-self 和 align-self

justify-self:子元素属性,垂直方向上的对齐形式,笼罩父元素中 justify-items 的值。具体的值和成果,同justify-items

align-self: 子元素属性,程度方向上的对齐形式,笼罩父元素中 align-items 的值。具体的值和成果,同align-items

容器属性

属性名 阐明 属性值
grid-template-rows
grid-template-columns
是基于网格行或者网格列的维度,去定义网格线的名称和网格轨道的尺寸大小。
grid-template-rows:设置行
grid-template-columns:设置列
grid-template-rows:基于网格行的轨道。
grid-template-columns:基于网格列的轨道。none:这个关键字示意不明确的网格。所有的行和其大小都将由 grid-auto-rows 属性隐式的指定。
长度 :非负值的长度大小。px,rem,百分比等。
fr:非负值,用单位 fr 来定义网格轨道大小的弹性系数。
minmax 函数:示意以后网格轨道的最大最小值。minmax(auto, 100px) 示意最大值 100px,主动最小值。
max-content:示意以网格项的最大的内容来占据网格轨道。
min-content:示意以网格项的最小的内容来占据网格轨道。
auto:如果该网格轨道为最大时,该属性等同于 max-content,为最小时,则等同于 min-content。
fit-content 函数:盒子会应用可用的空间,但永远不会超过 max-content。
repeat 函数:示意网格轨道的重复部分,以一种更简洁的形式去示意大量而且反复行的表达式。
grid-auto-rows
grid-auto-columns
指定隐式创立的行轨道大小。
grid-auto-rows:隐式行的大小。
grid-auto-columns:隐式列的大小。
长度 :px,百分比等。
fr:非负值,用单位 fr 来定义网格轨道大小的弹性系数。
minmax 函数:示意以后网格轨道的最大最小值。minmax(auto, 100px) 示意最大值 100px,主动最小值。
max-content:示意以网格项的最大的内容来占据网格轨道。
min-content:示意以网格项的最小的内容来占据网格轨道。
auto:如果该网格轨道为最大时,该属性等同于 max-content,为最小时,则等同于min-content
grid-template-areas 须要和网格布局容器的子元素的 grid-area 属性配合应用。参考上文中的“网格模板区域”大节。指定以后网格容器的子元素的网格区域。不能有 L 型区域或者扩散的同名区域。 多个字符串:每一个给定的字符串会生成一行,一个字符串中用空格分隔的每一个单元会生成一列。多个同名的,逾越相邻行或列的单元称为网格区块。非矩形的网格区块是有效的。
grid-template CSS 属性简写。蕴含了grid-template-rows,grid-template-columns,grid-template-areas grid-template-rows / grid-template-columns:同时指定网格行和网格列。比方:100px 1fr / 50px 1fr 2fr示意 2 行 3 列。
网格区域 + 行 / 列。
grid-auto-flow 管制着主动布局算法怎么运作,准确指定在网格中被主动布局的元素怎么排列。 row:指定主动布局算法依照通过逐行填充来排列元素,在必要时减少新行。
column:指定主动布局算法通过逐列填充来排列元素,在必要时减少新列。
dense:指定主动布局算法应用一种“浓密”沉积算法,如果前面呈现了稍小的元素,则会试图去填充网格中后面留下的空白。这样做会填上稍大元素留下的空白,但同时也可能导致原来呈现的秩序被打乱。
row dense:行优先的“浓密”沉积算法。
column dense:列优先的行无限的“浓密”沉积算法。
grid-row-gap
row-gap
指定网格行的间距。 长度:px,百分比等。
grid-column-gap
column-gap
指定网格列的间距。 长度:px,百分比等。
grid-gap
gap
指定网格行列的间距。会有两个值,第一个是行间距,第二个是列间距。如果没有列间距,那么示意列间距和行间距一样。 长度:px,百分比等。
grid CSS 属性简写。蕴含了grid-templategrid-gapgrid-auto-flow 值的组合形式有点简单,不倡议用吧,还是离开写代码可读性更好。
justify-items 垂直方向 (列维度) 的子元素在本人空间的对齐 start:对齐到最开始地位。
center:居中对齐
end:对齐到最开端。
stretch:拉伸子元素到撑满整个容器
align-items 程度方向 (行维度) 的子元素在本人空间的对齐 start:对齐到最开始地位。
center:居中对齐
end:对齐到最开端。
stretch:拉伸子元素到撑满整个容器
baseline:依照子元素的baseline 对齐
place-items justify-items 和 align-items 两个的缩写。先 align-items 再 justify-items。
justify-content 垂直方向上,子元素在容器空间中的对齐 start:对齐到最开始地位。
center:居中对齐
end:对齐到最开端。
space-between:多余空间均匀散布在子元素两头。
space-around:多余空间均匀盘绕在子元素两头
space-evenly:多余空间均匀散布子元素和容器边框之间。
stretch:拉伸子元素到撑满整个容器
align-content 程度方向上,子元素在容器空间中的对齐 justify-content
place-content justify-content 和 align-content 两个的缩写。先 align-content 再 justify-content。

我的项目属性

属性名 阐明 属性值
grid-column-start
grid-column-end
grid-column
指定以后网格区域的占据的列范畴。
grid-column-start指定开始的网格线。
grid-column-end指定完结的网格线。
grid-column是后面两个的缩写。程序是<grid-column-start> / <grid-column-end>
网格线:能够是网格线的数字,也能够是网格线的名字。
span:占据的网格列个数。比方 span 3 示意从当前列开始,占据 3 列。
grid-row-start
grid-row-end
grid-row
指定以后网格区域的占据的行范畴。
grid-column-start指定开始的网格线。
grid-column-end指定完结的网格线。
grid-column是后面两个的缩写。<grid-column-start> / <grid-column-end>
网格线 :能够是网格线的数字,也能够是网格线的名字。
span:占据的网格行个数。比方span 3 示意从以后行开始,占据 3 行。
grid-area 指定我的项目放在哪一个区域。有两种状况,
一种是指定名字,依据 grid-template-area 中的地位,进行指定。
另一种是指定网格线。
名字 :依据grid-template-area 中的设置的地位,进行定位。
网格线:指定 4 根网格线来确定网格区域。比方:1 / 2 / 3 / 4。程序是:grid-row-startgrid-column-startgrid-row-endgrid-column-end
justify-self 以后元素的垂直对齐形式。用于笼罩父容器指定的justify-items start:对齐到最开始地位。
center:居中对齐
end:对齐到最开端。
stretch:拉伸子元素到撑满整个容器
align-self 以后元素的程度对齐形式。用于笼罩父容器指定的align-items start:对齐到最开始地位。
center:居中对齐
end:对齐到最开端。
stretch:拉伸子元素到撑满整个容器
baseline:依照子元素的baseline 对齐
place-self justify-selfalign-self两个的缩写。先 align-selfjustify-self

总结

Grid 的内容有点多,这一篇整顿了概念和属性,算是“实践”篇,前面会再写一篇 Grid 的例子,当作“实际”篇。如果感觉学了不晓得用在哪里的,能够关注下。

完结

好了,本文到此结束,心愿本文对你有所帮忙 :-)
最近新弄了一个公粽号:写代码的浩,求关注 😄。前面会逐渐把把握的前端常识以及职场常识积淀下来。
如果还有什么疑难或者倡议,能够多多交换,原创文章,文笔无限,满腹经纶,文中若有不正之处,万望告知。

正文完
 0