瀑布流3种布局方式
- column-count (纯css)
- flex-box (纯css)
- js 计算每个元素绝对定位
布局优劣
- css
兼容性差,只能纵向排列,无法应用于动态加载
好处是容易写 - js
写起来麻烦,性能差
横向排布,能更好地利用空间,可支持动态加载
JS 布局代码
const waterfall = useCallback(() => {
const layer = document.getElementById('approval-desk')
const container: HTMLElement = _.get(document.getElementsByClassName('tabs-content'), '[0]')
const arr = document.getElementsByClassName('tabs-container') as HTMLCollectionOf<HTMLElement>
if (!layer || !container || !arr.length) return
if (document.documentElement.clientWidth <= 1020) {
container.style.cssText = ''
_.forEach(arr, item => { item.style.cssText = '' })
}
const layerWidth = layer.clientWidth
const clientRects = _.map(arr, item => item.getBoundingClientRect())
const columnWidth = clientRects[0].width
let columnCount = parseInt(`${layerWidth / columnWidth}`)
if (columnCount > clientRects.length) columnCount = clientRects.length
if (!columnCount) return
const cells = Array(columnCount).fill(1).map(() => []) as {
top: number,
height: number,
}[][]
container.style.cssText
= `position: relative; width: ${columnCount * columnWidth}px; margin: auto;`
let columnIndex = 0
for (let i = 0; i < clientRects.length; i++) {
const rect = clientRects[i]
const column = cells[columnIndex]
const lastColumnRect = column.length
? column[column.length - 1]
: { top: 0, height: 0 }
const newCell = {
top: lastColumnRect.top + lastColumnRect.height,
height: rect.height,
}
column.push(newCell)
arr[i].style.cssText
= `position: absolute; top: ${newCell.top}px; left: ${columnWidth * columnIndex}px`
const columnHeights = cells.map(column => _.sum(column.map(cell => cell.height)))
const minHeight = Math.min(...columnHeights)
columnIndex = columnHeights.findIndex(height => height === minHeight)
}
}, [])
useEffect(() => waterfall, [categories])
useEffect(() => {
window.addEventListener('resize', waterfall)
return () => window.removeEventListener('resize', waterfall)
}, [])