要实现这样的一个效果的, 光用css是flex或者float无法实现的,
要实现这样的效果,我们需要用到绝对定位,然后用到JavaScript,来计算每个卡片的left和top值
这里实现一个demo
首先创建一个卡片的容器
<div id="main">
</div>
加点样式
<style> * {
margin: 0;
padding: 0;
}
#main {
width: 1000px;
height: 800px;
background: #ccc;
display: flex;
position: relative;
padding: 10px;
overflow: auto;
}
#main>div {
outline: 1px solid #000;
position: absolute;
} </style>
我们假设卡片宽度是固定的,默认为100px
随机生成100组卡片数据
const Container = document.getElementById("main");
let totalWidth = Container.getBoundingClientRect().width
const DefaultWidth = 100;
function getRandom() {
return Math.ceil(((Math.random()) * 50)) + 100
}
function Color() {
let r = Math.ceil(Math.random() * 255);
let g = Math.ceil(Math.random() * 255);
let b = Math.ceil(Math.random() * 255);
return 'rgba(' + r + ',' + g + ',' + b + ',0.8)';
}
let data = [];
for (let i = 0; i < 100; i++) {
data.push({
height: getRandom(),
background: Color(),
})
}
然后遍历这100组数据生成卡片加入到容器中。
首次遍历时,保存下每列的高度,行列信息,
然后第一行填满后,剩下的行从没列的最矮的卡片开始填充剩余的卡片
以此逻辑填充完剩下的卡片。
代码逻辑如下
/* 行列信息*/
let rowColInfos = [];
let currentCol = 0;
let currentRow = 0;
//每行信息排序一次
let isSort = false;
//当前行是否铺满标
let mark = 0;
const frag = document.createDocumentFragment();
for (let d of data) {
let div = document.createElement("div");
div.style.width = DefaultWidth + "px";
div.style.height = d.height + "px";
div.style.backgroundColor = d.background;
frag.append(div);
//第一行,记录当前列的初始数据
if (currentRow === 0) {
heightData[currentCol] = {
height: d.height,
row: currentRow,
col: currentCol,
};
div.style.left = DefaultWidth * currentCol + "px";
div.style.top = 0;
if (DefaultWidth * (currentCol + 1) + DefaultWidth >= totalWidth) {
currentRow++;
}
else
currentCol++;
}
else {
//当前每列的高度,从低到高排序
if (!isSort) {
heightData.sort((d1, d2) => d1.height - d2.height);
isSort = true;
}
for (let info of heightData) {
//取当前行数据信息给与当前卡片的位置
if (info.row + 1 === currentRow) {
div.style.left = info.col * DefaultWidth + "px";
div.style.top = info.height + "px";
info.height += d.height;
mark++;
info.row++;
break;
}
}
//这行填充满了,进行下一轮填充
if (mark === heightData.length) {
mark = 0;
isSort = false;
currentRow++;
}
}
}
Container.appendChild(frag);
总结
这里简单实现了固定宽度的卡片自动填充,如果需要扩展,比如
1.加个过渡效果,需要第一次遍历便插入到元素中,第二次遍历改变元素位置
2.不同宽度,不同高度的自适应,那太复杂,需要用到比较高级的算法,一般不用用到
如果有更好的方法,也可留言交流。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。