grid基础用法解析
什么是grid布局
grid布局
是二维基于网格的布局模式,它与我们上一篇中提到的flex布局
,gpt上是这样回答的:
Flex布局主要针对一维布局(行或者列),可以方便地实现垂直居中、水平居中等效果,适合用于构建小规模的布局结构。而Grid布局则是基于二维网格来实现布局,可以对整个页面进行划分,并且支持各种复杂布局,比如交错布局、网格布局等等,适合用于构建大规模的布局结构。 具体区别如下:
- 方向不同:Flex布局只能沿着主轴(row 或 column)方向布局,不能同时控制两个方向,而Grid布局可以同时控制行列两个方向。
- 间隔不同:Flex布局无法设置单个子元素之间的间距,只能通过给父元素添加 padding 或 margin 来实现;而Grid布局可以通过 grid-column-gap 和 grid-row-gap 属性设置单元格之间的间距。
- 对齐方式不同:Flex布局提供了justify-content 和 align-items属性用于控制子元素在主轴和交叉轴上的对齐方式,而Grid布局提供了justify-items 和 align-items属性用于控制单元格内子元素的对齐方式。
- 排列方式不同:Flex布局使用flex-direction 属性控制子元素的排列方式,可以是 row(水平排列)或 column(垂直排列),而Grid布局使用grid-template-columns 和 grid-template-rows属性控制单元格的宽度和高度,从而控制子元素的排列方式。
grid-template-columns与grid-template-rows
<div class="container">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>
<style>
.container {
width: 300px;
border: 1px solid #ccc;
padding: 8px;
display: grid;
grid-template-columns: 40px 80px 100px 100px 40px;
grid-template-rows: 25% 100px auto;
}
.item {
height: 50px;
border: 1px solid #000;
}
</style>
从上图可以看出,在所有子元素给定宽度时候,没有自动换行,并且超出了预期的区域,如果需要在一行展示,可以将其中某个给定宽度,赋值auto
,例如:grid-template-columns: 40px 80px auto 100px 40px;
,则效果如下:
可以看出,第三个子元素宽度自适应,比之前的横向占的空间小了。
.container {
width: 300px;
border: 1px solid #ccc;
padding: 8px;
box-sizing: border-box;
display: grid;
grid-template-columns: 40px 80px 100px 100px 40px;
grid-template-rows: 10% 30% 200px;
}
.item {
border: 1px solid #000;
}
同样的,grid-template-rows
里面的参数也同样可以使用auto
代替。当多个重复数字时候,可以使用缩写的方式,例如:
.container { grid-template-columns: 70px 70px 70px 70px 100px;}
/* 等价于 */
.container { grid-template-columns: repeat(4, 70px) 100px; }
特殊单元fr
特殊单元fr
支持在固定子元素宽度的情况下,将剩余的部分,分成指定的分数,例如:
<div class="container">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>
<style>
.container {
width: 300px;
border: 1px solid #ccc;
padding: 8px;
box-sizing: border-box;
display: grid;
grid-template-columns: 1fr 1fr 1fr;
}
.item {
border: 1px solid #000;
height: 50px;
}
</style>
像这样,平均分为了指定的大小,也换行了。如果我们将上述的1fr 1fr 1fr
改成1fr 2fr 1fr
,又会是什么样的效果呢?
截止目前,每行都是三个元素展示,这是因为我们在单行定义了三个份额,如果要展示两个,我们只需要将上述代码中的1fr 2fr 1fr
改成1fr 2fr
,就会出现一行展示两个的效果了,效果如下:
使用grid-template-areas
实现简单布局
<div class="container">
<div class="item-a item">header</div>
<div class="item-b item">main</div>
<div class="item-c item">sidebar</div>
<div class="item-d item">footer</div>
</div>
<style>
.item { border: 1px solid #000; }
.item-a { grid-area: header; }
.item-b { grid-area: main; }
.item-c { grid-area: sidebar; }
.item-d { grid-area: footer; }
.container {
width: 300px;
height: 200px;
border: 1px solid #ccc;
padding: 8px;
display: grid;
grid-template-columns: 1fr 1fr 1fr 1fr;
grid-template-rows: auto;
grid-template-areas:
"header header header header"
"sidebar . main main"
"footer footer footer footer";
}
</style>
<grid-area-name>
:在grid-area
中指定的网格区域名字.
:一个句点表示一个空的网格单元none
:没有网格区域被定义
在上面的代码里,grid-area
属性指定网格模板,grid-template-areas
属性对模板进行排版排序,为了方便对比理解,我们将代码中排序的顺序与效果图放在一起进行对比,如下图:
我们不难看出,因为我们将网格分为了四等份grid-template-columns: 1fr 1fr 1fr 1fr;
,所以排序时候,一行也按照多个进行排列,相同模板的单元会被自动合并在一起。或许有同学会问,那如果我分为四等份,但是我排版时候,一行排五个,会怎样呢?使用none
排版又怎样呢?我们也给出了效果图如下(左侧为一行排列五个效果;右侧为none
效果):
grid-column-gap/grid-row-gap/grid-gap
在上面,我们已经能够通过grid进行简单的布局,但是我们可以发现,子元素网格模板之间是紧挨着的,没有间隙,并不符合我们想象中的样子,所以我们就需要添加行列模板之间的间隙。话不多说,我们直接上代码:
<div class="container">
<div class="item-a item">header</div>
<div class="item-b item">main</div>
<div class="item-c item">sidebar</div>
<div class="item-d item">footer</div>
</div>
<style>
.item { border: 1px solid #000; }
.item-a { grid-area: header; }
.item-b { grid-area: main; }
.item-c { grid-area: sidebar; }
.item-d { grid-area: footer; }
.container {
width: 300px;
height: 200px;
border: 1px solid #ccc;
padding: 8px;
display: grid;
grid-template-columns: 1fr 1fr 1fr 1fr;
grid-template-rows: auto;
grid-template-areas:
"header header header header"
"sidebar . main main"
"footer footer footer footer";
grid-column-gap: 16px;
grid-row-gap: 32px;
}
</style>
从图中我们可以看出,在网格模板中,行之间的间隙是32px,列之间的间隙是16px。
我们可以将两个属性写在一起,例如:grid-gap: <grid-column-gap> <grid-row-gap>;
justify-items网格对齐方式
网格默认stretch
对齐,填充整个网格区域的宽度,start,center,end对齐会失去平铺的效果,效果如下:
align-items网格对齐方式
网格默认stretch
对齐,填充整个网格区域的宽度,start,center,end对齐会失去平铺的效果,效果如下:
justify-content/align-content
当给定的宽度和小于父元素宽度或高度就会出现盒子边缘大量空白,但是想要两端对齐或者环绕对齐,就可以这样做,情景复现:
<div class="container">
<div class="item-a item">header</div>
<div class="item-b item">main</div>
<div class="item-c item">sidebar</div>
<div class="item-d item">footer</div>
</div>
<style>
.item { border: 1px solid #000; }
.item-a { grid-area: header; }
.item-b { grid-area: main; }
.item-c { grid-area: sidebar; }
.item-d { grid-area: footer; }
.container {
width: 300px;
height: 200px;
border: 1px solid #ccc;
padding: 8px;
display: grid;
grid-template-columns: 50px 50px 50px 50px;
grid-template-rows: 50px 50px 50px;
grid-template-areas:
"header header header header"
"sidebar main main main"
"footer footer footer footer";
}
</style>
下面是一张在W3CSchool找到的关于justify-content
的描述及效果图:
start
:左对齐end
:右对齐center
:居中对齐stretch
:填充网格容器space-around
:在每个网格子项中间放置均等的空间,在始末两端只有一半大小space-between
:两边对齐,在每个网格子项中间放置均等的空间,在始末两端没有空间space-evenly
:网格间隔相等,包括始末两端
下面是一张在W3CSchool找到的关于align-content
的描述及效果图:
start
:顶部对齐end
:底部对齐center
:居中对齐stretch
:填充网格容器space-around
:在每个网格子项中间放置均等的空间,在始末两端只有一半大小space-between
:上下对齐,在每个网格子项中间放置均等的空间,在始末两端没有空间space-evenly
:在每个网格子项中间放置均等的空间,包括始末两端
我们通过justify-content
与align-content
,对上面我们的布局进行调整,代码及效果如下:
<div class="container">
<div class="item-a item">header</div>
<div class="item-b item">main</div>
<div class="item-c item">sidebar</div>
<div class="item-d item">footer</div>
</div>
<style>
.item { border: 1px solid #000; }
.item-a { grid-area: header; }
.item-b { grid-area: main; }
.item-c { grid-area: sidebar; }
.item-d { grid-area: footer; }
.container {
width: 300px;
height: 200px;
border: 1px solid #ccc;
padding: 8px;
display: grid;
grid-template-columns: 50px 50px 50px 50px;
grid-template-rows: 50px 50px 50px;
grid-template-areas:
"header header header header"
"sidebar main main main"
"footer footer footer footer";
justify-content: space-around;
align-content: space-around;
}
</style>
通过grid-auto-flow控制排列方式
row
:按照行依次从左到右排列column
:按照列依次从上到下排列dense
:按先后顺序排列
grid-auto-flow: row
<div class="container">
<div class="item-a item">item-a</div>
<div class="item-b item">item-b</div>
<div class="item-c item">item-c</div>
<div class="item-d item">item-d</div>
<div class="item-e item">item-e</div>
</div>
<style>
.item {
border: 1px solid #000;
}
.container {
width: 300px;
height: 200px;
border: 1px solid #ccc;
padding: 8px;
display: grid;
grid-template-columns: 1fr 1fr 1fr 1fr 1fr;
grid-template-rows: repeat(5, 40px);
grid-auto-flow: row;
}
.item-a {
grid-column: 1;
grid-row: 1 / 2;
background-color: #ccc;
}
.item-c {
grid-column: 3;
grid-row: 2 / 4;
background-color: #ccc;
}
.item-e {
grid-column: 5;
grid-row: 1 / 3;
background-color: #ccc;
}
</style>
从上图中我们可以看出,grid-row
属性,最小值为1,截止于给定值的上一个值,例如item-e
,给定的值为第一行到第三行,但实际上只渲染了前两行。
<div class="container">
<div class="item-a item">item-a</div>
<div class="item-b item">item-b</div>
<div class="item-c item">item-c</div>
<div class="item-d item">item-d</div>
<div class="item-e item">item-e</div>
</div>
<style>
.item {
border: 1px solid #000;
}
.container {
width: 300px;
height: 200px;
border: 1px solid #ccc;
padding: 8px;
display: grid;
grid-template-columns: 1fr 1fr 1fr 1fr 1fr;
grid-template-rows: repeat(6, 40px);
grid-auto-flow: column;
}
.item-a {
grid-row: 1;
grid-column: 1 / 2;
background-color: #ccc;
}
.item-c {
grid-row: 3;
grid-column: 2 / 4;
background-color: #ccc;
}
.item-e {
grid-row: 5;
grid-column: 1 / 3;
background-color: #ccc;
}
</style>
justify-self/align-self
justify-self属性介绍
start
– 让内容在网格区域左对齐end
– 让内容在网格区域右对齐center
– 让内容在网格区域中间对齐stretch
– 填充着呢个网络区域的宽度(默认值)
justify-self: start | end | center | stretch
align-self属性介绍
start
– 让内容在网格区域上对齐end
– 让内容在网格区域下对齐center
– 让内容在网格区域中间对齐stretch
– 填充着呢个网络区域的高度(默认值)
align-self: start | end | center | stretch
将上面案例的文字,横向居中,纵向也居中:
<div class="container">
<div class="item">hello</div>
<div class="item">hello</div>
<div class="item">hello</div>
<div class="item">hello</div>
<div class="item">hello</div>
</div>
<style>
.container {
width: 300px;
border: 1px solid #ccc;
padding: 8px;
box-sizing: border-box;
display: grid;
grid-template-columns: 1fr 1fr 1fr;
}
.item {
border: 1px solid #000;
height: 50px;
display: grid;
align-items: center;
justify-items: center;
}
</style>
小结
grid布局是一种灵活而强大的CSS布局方法,我们可以以网格形式排列页面元素。与传统的基于盒模型的布局技术相比,grid布局提供了更直观、更简单的方式来定义和控制页面布局。
flex布局的优点:
- 简单易学:相对于grid,flex更容易上手。
- 适用于一维布局:flex最擅长处理一维布局(即沿着一个轴线排列元素),比如垂直居中、水平布局等。
- 响应式布局:flex可用于创建弹性、响应式布局,可以在不同设备上灵活适配。
- 浏览器支持较好:flex已成为布局的标准之一,并且大多数浏览器都支持。
flex布局的缺点:
- 二维布局限制:相对于grid,flex更适用于处理一维布局,因此在需要处理复杂布局时,它的能力会受到限制。
- 对齐方式受限:使用flex时,对齐方式只能沿着主轴线和交叉轴线两个方向进行,这也就意味着某些特殊的布局需求可能无法满足。
grid布局的优点:
- 适用于二维布局:grid最大的优势在于其能够轻松处理复杂的二维布局,包括列和行。
- 灵活性强:grid具有较高的灵活性,可以轻松地实现响应式布局,同时还可以应对各种尺寸和设备。
- 对齐方式灵活:相比flex,grid对齐方式的限制更少,用户可以将元素沿着任意方向进行排列。
grid布局的缺点:
- 学习曲线较陡峭:相对于flex,gid的学习曲线可能会更陡峭一些。
- 浏览器兼容性问题:虽然大多数浏览器都支持grid,但在一些老旧浏览器上可能存在兼容性问题。
虽然grid布局相比flex布局更加强大,但是我们在使用的过程中,还是要二者配合使用,才能更快更高效的实现我们需要的布局。
转载自:https://juejin.cn/post/7238978371689381945