介绍
之前写过两篇文章,分别讲解了Flex布局和网格布局。然后有很多人反馈说。网格布局没有场景,学会Flex布局就可以了。
今天这篇文章就通过一个例子来讲解一下网格布局的优势。并不是说Flex布局无法实现。而是说在某些场景下使用Flex布局逻辑会不清晰,代码会复杂很多。
手机桌面的小组件
今天要举的例子就是从手机桌面上面来的。现在的手机桌面上,可以自定义的放一些App图标,也可以添加很多小组件。就拿我的苹果手机来举例。一个桌面,它会有4列的图标,然后在这些桌面上可以任意添加小组件。小组件可能是一行4列或者是两行两列等各种情况。
如果我们用前端页面来实现这种效果的话,该怎么做呢?
Flex实现
大家可以先自己想想看这种布局用Flex该怎么实现。
如果使用Flex布局的方式来实现这个需求。我们会发现使用Flex布局会很麻烦,需要用js去提前计算,当前行是否存在一行多列的组件,或者多行一列的组件。得出布局结构后,再去做第一层的div
,以及第二层div
。
这里的逻辑太麻烦,我就不写了。有兴趣可以自己去尝试写写看。
Grid实现
首先会有一个父节点。他是一个是列多行的网格容器。为了避免留下空白,我们设置自动布局算法为dense
。
<div class="grid-box" id="box"></div>
下面是CSS:
.grid-box {
border: 1px solid #999;
width: 200px;
height: 400px;
display: grid;
margin: 20px;
grid-template-columns: repeat(4, 1fr);
grid-template-rows: repeat(8, 1fr);
gap: 6px;
padding: 6px;
grid-auto-flow: dense;
}
.grid-box > div {
background-color: bisque;
border-radius: 4px;
border: 1px solid #ccc;
}
假设桌面的图标或小组件,可以选择1x1,1x2,2x1,2x2四种效果。所以我们可以先设置三种大小的子节点空间,因为默认是1x1,所以1x1不需要单独这种。有了这几个class
我们创建子节点的时候,只要往上面添加这个对应的class
就能实现对应的效果。
.grid-box-item-1 {
grid-column-end: span 2; /* 1x2 */
}
.grid-box-item-2 {
grid-row-end: span 2; /* 2x1 */
}
.grid-box-item-3 { /* 2x2 */
grid-column-end: span 2;
grid-row-end: span 2;
}
因为要控制随机位置,网格布局并不像Flex布局那样,可以指定子节点的顺序。所以这个子节点要通过JS往容器append
。
function randomItem() {
let styleArr = [0,0,0,0,1,1,2,3];
let itemsEl = '';
for (let i = 0; i < styleArr.length; i++) {
itemsEl += `<div class="grid-box-item-${styleArr[i]}">${i}</div>`;
}
boxEl.innerHTML = itemsEl;
}
randomItem();
效果如图:
最后我们对样式数组做一个随机。
function randomItem() {
let styleArr = [0,0,0,0,1,1,2,3];
styleArr = styleArr.sort(() => {
return Math.random() > 0.5 ? 1 : -1;
});
// ...
}
当我们每次重新调用randomItem
方法之后,都会对子节点做一个随机的摆放。效果如图:
总结
还是上面的例子,如果布局结构是固定的,那么使用Flex布局其实也不复杂,但是一有变化,Flex就复杂了。
可以看出,使用Flex能够快速解决大部分的场景了,这个也就是之前很多人评论的,找不到使用Grid布局的场景,没必要学Grid布局。
但是一旦遇到一些特殊不情况,不知道Grid布局,就只能使用Flex,那么代码就会又臭又长。
结束
好了,本文到此结束,希望本文对你有所帮助 :-)
最近新弄了一个公粽号:写代码的浩,求关注 😄。后面会逐步把掌握的前端知识以及职场知识沉淀下来。
如果还有什么疑问或者建议,可以多多交流,原创文章,文笔有限,才疏学浅,文中若有不正之处,万望告知。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。