要實現這樣的一個效果的, 光用css是flex或者float沒法實現的,css
要實現這樣的效果,咱們須要用到絕對定位,而後用到JavaScript,來計算每一個卡片的left和top值算法
這裏實現一個demoapp
首先建立一個卡片的容器dom
<div id="main"> </div>
加點樣式flex
<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>
咱們假設卡片寬度是固定的,默認爲100pxspa
隨機生成100組卡片數據code
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組數據生成卡片加入到容器中。blog
首次遍歷時,保存下每列的高度,行列信息,排序
而後第一行填滿後,剩下的行從沒列的最矮的卡片開始填充剩餘的卡片ip
以此邏輯填充完剩下的卡片。
代碼邏輯以下
/* 行列信息*/ 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.不一樣寬度,不一樣高度的自適應,那太複雜,須要用到比較高級的算法,通常不用用到
若是有更好的方法,也可留言交流。