学会Grid之后,我觉得再也没有我搞不定的布局了

程序员他爱做梦 2024-02-23 03:53:55

说到布局很多人的感觉应该都是恐惧,为此很多人都背过一些很经典的布局方案,例如:圣杯布局、双飞翼布局等非常耳熟的名词;

为了实现这些布局我们有很多种实现方案,例如:table布局、float布局、定位布局等,当然现在比较流行的肯定是flex布局;

flex布局属于弹性布局,所谓弹性也可以理解为响应式布局,而同为响应式布局的还有Grid布局;

Grid布局是一种二维布局,可以理解为flex布局的升级版,它的出现让我们在布局方面有了更多的选择,废话不多说,下面开始全程高能;

本篇不会过多介绍grid的基础内容,更多的是一些布局的实现方案和一些小技巧;

常见布局

所谓的常见布局只是我们在日常开发中经常会遇到的布局,例如:圣杯布局、双飞翼布局这种名词我个人觉得不用太过于去在意;

因为这类布局最后的解释都会变成几行几列,内容在哪一行哪一列,而这些就非常直观的对标了grid的特性;

接下来我们来一起看看一些非常常见的布局,并且用grid来实现;

1. 顶部 + 内容

<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title> <style> html, body { margin: 0; padding: 0; } body { display: grid; grid-template-rows: 60px 1fr; height: 100vh; } .header { background-color: #039BE5; } .content { background-color: #4FC3F7; } .header, .content { display: flex; align-items: center; justify-content: center; font-size: 24px; } </style></head><body><div>

2. 顶部 + 内容 + 底部

<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title> <style> html, body { margin: 0; padding: 0; } body { display: grid; grid-template-rows: 60px 1fr 60px; height: 100vh; } .header { background-color: #039BE5; } .content { background-color: #4FC3F7; } .footer { background-color: #039BE5; } .header, .content, .footer { display: flex; align-items: center; justify-content: center; font-size: 24px; } </style></head><body><div>

这里示例和上面的示例唯一的区别就是多了一个footer,但是我们可以看到代码并没有多少变化,这就是grid的强大之处;

可以看码上掘金的效果,这里的内容区域是单独滚动的,从而实现了header和footer固定,内容区域滚动的效果;

实现这个效果也非常简单,只需要在content上加上overflow: auto即可;

3. 左侧 + 内容

<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title> <style> html, body { margin: 0; padding: 0; } body { display: grid; grid-template-columns: 240px 1fr; height: 100vh; } .left { background-color: #039BE5; } .content { background-color: #4FC3F7; } .left, .content { display: flex; align-items: center; justify-content: center; font-size: 24px; } </style></head><body><div>

这个示例效果其实和第一个是类似的,只不过是把grid-template-rows换成了grid-template-columns,这里就不提供码上掘金的示例了;

4. 顶部 + 左侧 + 内容

<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title> <style> html, body { margin: 0; padding: 0; } body { display: grid; grid-template-rows: 60px 1fr; grid-template-columns: 240px 1fr; height: 100vh; } .header { grid-column: 1 / 3; background-color: #039BE5; } .left { background-color: #4FC3F7; } .content { background-color: #99CCFF; } .header, .left, .content { display: flex; align-items: center; justify-content: center; font-size: 24px; } </style></head><body><div>

这个示例不同点在于header占据了两列,这里我们可以使用grid-column来实现,grid-column的值是start / end,例如:1 / 3表示从第一列到第三列;

如果确定这一列是占满整行的,那么我们可以使用1 / -1来表示,这样如果后续变成顶部 + 左侧 + 内容 + 右侧的布局,那么header就不需要修改了;

5. 顶部 + 左侧 + 内容 + 底部

<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title> <style> html, body { margin: 0; padding: 0; } body { display: grid; grid-template-areas: "header header" "left content" "left footer"; grid-template-rows: 60px 1fr 60px; grid-template-columns: 240px 1fr; height: 100vh; } .header { grid-area: header; background-color: #039BE5; } .left { grid-area: left; background-color: #4FC3F7; } .content { grid-area: content; background-color: #99CCFF; } .footer { grid-area: footer; background-color: #6699CC; } .header, .left, .content, .footer { display: flex; align-items: center; justify-content: center; font-size: 24px; } </style></head><body><div>

这个示例的小技巧是使用了grid-template-areas,使用这个属性可以让我们通过代码来直观的看到布局的样式;

这里的值是一个字符串,每一行代表一行,每个字符代表一列,例如:"header header"表示第一行的两列都是header,这里的header是我们自己定义的,可以是任意值;

定义好了之后就可以在对应的元素上使用grid-area来指定对应的区域,这里的值就是我们在grid-template-areas中定义的值;

在码上掘金中的效果可以看到,左侧的菜单和内容区域都是单独滚动的,这里的实现方式和第二个示例是一样的,只需要需要滚动的元素上加上overflow: auto即可;

响应式布局

响应式布局指的是页面的布局会随着屏幕的大小而变化,这里的变化可以是内容区域大小可以自动调整,也可以是页面布局随着屏幕大小进行自动调整;

这里我就用掘金的页面来举例,这里只提供一个思路,所以不会像上面那样提供那么多示例;

1. 基础布局实现移动端布局

以移动端的效果开始,掘金的移动端的布局就是上面的效果,这里我简单的将页面分为了三个部分,分别是header、navigation、content;

注:这里不是要100%还原掘金的页面,只是为了演示grid布局,具体页面结构和最后实现的效果会有非常大的差异,这里只会实现一些基础的布局;

<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title> <style> html, body { margin: 0; padding: 0; } body { display: grid; grid-template-areas: "header" "navigation" "content"; grid-template-rows: 60px 48px 1fr; height: 100vh; } .header { grid-area: header; background-color: #039BE5; } .navigation { grid-area: navigation; background-color: #4FC3F7; } .content { grid-area: content; background-color: #99CCFF; } .header, .navigation, .content { display: flex; align-items: center; justify-content: center; font-size: 24px; } </style></head><body><div>

iPad布局

这里是需要借助媒体查询来实现的,在媒体查询中只需要调整一下grid-template-rows和grid-template-columns的值即可;

由于这里的效果是上面一个的延伸,为了阅读体验会移除上面相关的css代码,只保留需要修改的代码;

<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title> <style> .right { display: none; background-color: #6699CC; } @media (min-width: 1000px) { body { grid-template-areas: "header header" "navigation navigation" "content right"; grid-template-columns: 1fr 260px; } .right { grid-area: right; display: flex; align-items: center; justify-content: center; font-size: 24px; } } </style></head><body><div>

PC端布局

和上面处理方式相同,由于Navigation移动到了左侧,所以还要额外的修改一下grid-template-areas的值;

这里就可以体现grid的强大之处了,我们可以简单的修改grid-template-areas就可以实现一个完全不同的布局,而且代码量非常少;

为了居中显示内容,我们需要在左右两侧加上一些空白区域,可以简单的使用.来实现,这里的.表示一个空白区域;

由于内容的宽度基本上是固定的,所以留白区域简单的使用1fr进行占位即可,这样就可以平均的分配剩余的空间;

<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title> <style> @media (min-width: 1220px) { body { grid-template-areas: "header header header header header" ". navigation content right ."; grid-template-columns: 1fr 180px minmax(0, 720px) 260px 1fr; grid-template-rows: 60px 1fr; } } </style></head><body><div>

完善一些细节

最终的布局大概就是上图这样,这里主要处理的各个版块的间距和响应式内容区域的大小,这里的处理方式主要是使用column-gap和一个空的区域进行占位来实现的;

这里的column-gap表示列与列之间的间距,值可以是px、em、rem等基本的长度属性值,也可以使用计算函数,但是不能使用弹性值fr;

空区域进行占位留间距其实我并不推荐,这里只是演示grid布局可以实现的一些功能,具体的实现方式还是要根据实际情况来定,这里我更推荐使用margin来实现;

完整代码如下:

<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title> <style> html, body { margin: 0; padding: 0; } body { display: grid; grid-template-areas: "header header header" "navigation navigation navigation" ". . ." ". content ."; grid-template-columns: 1fr minmax(0, 720px) 1fr; grid-template-rows: 60px 48px 10px 1fr; column-gap: 10px; height: 100vh; } .header { grid-area: header; background-color: #039BE5; } .navigation { grid-area: navigation; background-color: #4FC3F7; } .content { grid-area: content; background-color: #99CCFF; } .right { display: none; background-color: #6699CC; } @media (min-width: 1000px) { body { grid-template-areas: "header header header header" "navigation navigation navigation navigation" ". . . ." ". content right ."; grid-template-columns: 1fr minmax(0, 720px) 260px 1fr; } .right { grid-area: right; display: flex; align-items: center; justify-content: center; font-size: 24px; } } @media (min-width: 1220px) { body { grid-template-areas: "header header header header header" ". . . . ." ". navigation content right ."; grid-template-columns: 1fr 180px minmax(0, 720px) 260px 1fr; grid-template-rows: 60px 10px 1fr; } } .header, .navigation, .content { display: flex; align-items: center; justify-content: center; font-size: 24px; } </style></head><body><div>

简单复刻版

以码上掘金上的效果来说已经完成了大部分的布局和一些效果,目前来说就是还差一些交互,还有一些细节上的处理,感兴趣的同学可以自行完善;

异型布局

异性布局指的是页面中的元素不是按照常规的流式布局进行排版,又或者说不规则的布局,这里我简单的列出几个布局,来看看grid是如何实现的;

1. 照片墙

<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title> <style> html, body { margin: 0; padding: 0; background: #f2f3f5; overflow: auto; } body { display: grid; grid-template-columns: repeat(12, 100px); grid-auto-rows: 100px; place-content: center; gap: 6px; height: 100vh; } .photo-item { width: 200px; height: 200px; clip-path: polygon(50% 0, 100% 50%, 50% 100%, 0 50%); } </style></head><body></body><script> function randomColor() { return '#' + Math.random().toString(16).substr(-6); } let row = 1; let col = 1; for (let i = 0; i < 28; i++) { const div = document.createElement('div'); div.className = 'photo-item'; div.style.backgroundColor = randomColor(); div.style.gridRow = `${row} / ${row + 2}`; div.style.gridColumn = `${col} / ${col + 2}`; document.body.appendChild(div); col += 2; if (col > 11) { row += 1; col = row % 2 === 0 ? 2 : 1; } }</script></html>

这是一个非常简单的照片墙效果,如果不使用grid的话,我们大概率是会使用定位去实现这个效果,但是换成grid的话就非常简单了;

而且代码量是非常少的,这里就不提供码上掘金的 demo 了,感兴趣的同学可以将代码复制下来自行查看效果;

2. 漫画效果

在漫画中有很多类似这种不规则的漫画框,如果使用定位的话,那么代码量会非常大,而且还需要计算一些位置,使用grid的话就非常简单了;

可以看到这里还有一个气泡文字显示的效果,按照页面书写顺序,气泡是不会显示的,这里我们可以使用z-index来实现,这里的z-index值越大,元素就越靠前;

而且气泡文字效果也是通过grid来进行排版的,并没有使用其他的布局来实现,代码量也并不多,感兴趣的同学可以自行查看;

3. 画报效果

在一个画报中,我们经常会看到文字和图片混合排版的效果,由于这里直接使用的是渐变的背景,而且我的文字都是随意进行排列的,没有什么规律,所以看起来会比较混乱;

在画报效果中看似文字排版非常混乱不规则,但是实际上设计师在设计的时候也是会划分区域的,当然用定位也是没问题的,但是使用grid的话就会简单很多;

我这里将页面划分为12 * 12区域的网格,然后依次对不同的元素进行单独排列和样式的设置;

流式布局

流式布局指的是页面的内容会随着屏幕的大小而变化,流式布局也可以理解为响应式布局;

但是不同于响应式布局的是,流式布局的布局不会像响应式布局那样发生变化,只是内容会随着轴进行流动;

通常这种指的是grid-template-columns: repeat(auto-fit, minmax(0, 1fr))这种;

直接看效果:

这里有两个关键字,一个是auto-fit,还有一个是auto-fill,在行为上它们是相同的,不同的是它们在网格创建的不同,

就像上面图中看到的一样,使用auto-fit会将空的网格进行折叠,可以看到他们的结束colum的数字都是6;

像我们上面的实例中不会出现这个问题,因为我们使用了响应式单位fr,只有使用固定单位才会出现这个现象;

感兴趣的同学可以将minmax(200px, 1fr)换成200px尝试;

对比 Flex 布局

在我上面介绍了这么多的布局场景和案例,其实可以很明显的发现一件事,那就是我使用grid进行的布局基本上都是大框架;

当然上面也有一些布局使用flex也是可以实现的,但是我们再换个思路,除了flex可以做到上面的一些布局,float布局、table布局、定位布局其实也都能实现;

不同的是float布局、table布局、定位布局基本上都是一些hack的方案,就拿table布局来说,table本身就是一个html标签,作用就是用来绘制表格,被拿来当做布局的一种方案也是迫不得已;

而web布局发展到现在的我们有了正儿八经可以布局的方案flex,为什么又要出一个grid呢?

grid的出现绝对不是用来替代flex的,在我上面的实现的一些布局案例中,也可以看到我还会使用flex;

我个人理解的是使用grid进行主体的大框架的搭建,flex作为一些小组件的布局控制,两者搭配使用;

flex能实现一些grid不好实现的布局,同样grid也可以实现flex实现困难的布局;

本身它们的定位就不痛,flex作为一维布局的首选,grid定位就是比flex高一个维度,它的定位是二维布局,所以他们之间没有必要进行对比,合理使用就好;

总结

上面介绍的这么多基于grid布局实现的布局方案,足以看出grid布局的强大;

grid布局的体系非常庞大,本文只是梳理出一些常见的布局场景,通过grid布局去实现这些布局,来体会grid带来的便利;

可能需要完全理解我上面的全部示例需要对grid有一定的了解才可以,但是都看到这里了,不妨去深挖一下;

grid布局作为一项强大的布局技术,有望在未来继续发展,除了我上面说到的布局,grid还有很多小技巧来实现非常多的布局场景;

碍于我的见识和文笔的限制,我这次介绍grid肯定是有很多不足的,但是还是希望这篇文章能为你对于布局相关能有新的认识;

作者:田八链接:https://juejin.cn/post/7310423470546354239

0 阅读:1

程序员他爱做梦

简介:感谢大家的关注