效果图
前言
本篇实现是对于上一篇 也许是最简单的纯 CSS 实现瀑布流布局!!! 中以 columns 多列布局 实现瀑布流所存在的局限进行解决,这里的布局参考了一下蘑菇街 的实现。
HTML&CSS
<style>
.box-wrapper {
display: flex;
}
.column-box {
flex: 1;
margin-right: 20px;
}
.box-wrapper .column-box:last-child {
margin-right: 0;
}
</style>
<div class="box-wrapper">
<div class="column-box"></div>
<div class="column-box"></div>
<div class="column-box"></div>
<div class="column-box"></div>
</div>
以上只是为了实现下述这张图,然后将一些高度不一的盒子加进去便实现了瀑布流:
那么实现瀑布流的关键无非就这几种:多列、元素参差不齐排列、懒加载。不同于 columns 布局的是,上述的布局需要将子元素添加到多个父级中,并且要实现符合我们日常场景的排序。也不难,代码如下:
排序
符合我们日常场景的排序:排序1的放在第一个长条里,排序2的放在第二个长条里,排序3的放在第三个长条里,排序4的放在第四个长条里,依次循环类推……也不难写出下面代码:
let counter = 0
let arrays = [[], [], [], []]
function pushItem(current, arrIndex) {
current % 4 === arrIndex && arrays[arrIndex].push(++counter)
}
for (let i = 0; i < 20; i++) {
pushItem(i, 0)
pushItem(i, 1)
pushItem(i, 2)
pushItem(i, 3)
}
console.log(arrays);
// [
// [ 1, 5, 9, 13, 17 ],
// [ 2, 6, 10, 14, 18 ],
// [ 3, 7, 11, 15, 19 ],
// [ 4, 8, 12, 16, 20 ]
// ]
完整JS
通过上述的排序代码结合上一篇的 js 实现代码,稍改后的 js 代码如下:
<script>
let counter = 0
const INITIAL_NUMBER = 40
const MAX_HEIGHT = 400
const MIN_HEIGHT = 200
const columnBoxList = document.querySelectorAll('.column-box')
function createDiv() {
const div = document.createElement('div')
const randomHeight = Math.floor(Math.random() * (MAX_HEIGHT - MIN_HEIGHT + 1) + MIN_HEIGHT)
div.innerHTML = `${++counter}`
div.style.height = `${randomHeight}px`
div.classList.add('box-item')
return div
}
function createFragments(num) {
const fragments = []
for (let j = 0; j < 4; j++) {
fragments.push(document.createDocumentFragment())
}
function pushItem(current, arrIndex) {
current % 4 === arrIndex && fragments[arrIndex].appendChild(createDiv())
}
for (let i = 0; i < num; i++) {
pushItem(i, 0)
pushItem(i, 1)
pushItem(i, 2)
pushItem(i, 3)
}
return fragments
}
function createLoading() {
let loading = document.querySelector('.loading')
if (!loading) {
loading = document.createElement('div')
loading.classList.add('loading')
}
return loading
}
function appendHandler(num) {
const elements = createFragments(num)
columnBoxList.forEach((column, i) => {
column.appendChild(elements[i])
})
}
function init() {
appendHandler(INITIAL_NUMBER)
}
function scrollHandler() {
const {scrollTop, clientHeight, offsetHeight} = document.documentElement
const nearBottom = offsetHeight - clientHeight === scrollTop
if (nearBottom) {
const loading = createLoading()
document.body.appendChild(loading)
setTimeout(() => {
document.body.removeChild(loading)
appendHandler(20)
}, 1000)
}
}
function debounce(callback, delay) {
let timer = null
return function () {
clearTimeout(timer)
timer = setTimeout(callback, delay)
}
}
window.addEventListener('load', init)
window.addEventListener('scroll', debounce(scrollHandler, 100))
</script>
子元素的高度差异不要过大,这样的排序效果还是非常符合我们的日常直觉的。以上便是我探索 瀑布流布局 的全部了,更详细的代码点击 这里。