已知红色区域尺寸位置 如何用最少div填充页面其余空白区域
实现思路
- 前提假设:所有红色区域均为轴对齐矩形,且你已经掌握每个红色块的
left/top/width/height属性 - 核心算法采用矩形空间递归分割法,可以保证生成的div数量最少,完全不会覆盖红色区域,且填满所有剩余空间:
- 第一步:先把整个页面作为初始的待分割大矩形
- 第二步:找出当前待分割矩形范围内的所有红色矩形,取第一个红色矩形作为切割锚点
- 第三步:以这个红色矩形为边界,把当前待分割大矩形切为最多4个独立的空白矩形:红色块上方区域、红色块下方区域、红色块左侧区域、红色块右侧区域
- 第四步:对切出来的每个空白矩形,递归执行第二步到第三步的操作,直到当前待分割矩形范围内没有任何红色块,就把这个矩形作为最终的填充div
- 浮动布局适配:生成每个div的时候直接设置
float: left(或者根据排列需求设置float: right),再对应设置width/height/margin属性即可,不需要额外定位
示例核心实现代码
// 入参说明: // pageRect: 页面总尺寸 {x: 0, y: 0, w: 页面宽度, h: 页面高度} // redBlocks: 所有红色矩形数组,每个元素格式为{x: 左偏移, y: 上偏移, w: 宽度, h: 高度} function generateFillDivs(pageRect, redBlocks) { const result = [] // 递归切割函数 function splitRect(currentRect, blocks) { // 过滤出和当前矩形相交的红色块 const overlapBlocks = blocks.filter(b => b.x < currentRect.x + currentRect.w && b.x + b.w > currentRect.x && b.y < currentRect.y + currentRect.h && b.y + b.h > currentRect.y ) // 没有重叠红色块,直接加入结果 if (overlapBlocks.length === 0) { result.push(currentRect) return } // 取第一个重叠的红色块作为切割锚点 const anchor = overlapBlocks[0] // 切割出上方区域 if (anchor.y > currentRect.y) { splitRect({ x: currentRect.x, y: currentRect.y, w: currentRect.w, h: anchor.y - currentRect.y }, blocks) } // 切割出下方区域 if (anchor.y + anchor.h < currentRect.y + currentRect.h) { splitRect({ x: currentRect.x, y: anchor.y + anchor.h, w: currentRect.w, h: currentRect.y + currentRect.h - (anchor.y + anchor.h) }, blocks) } // 切割出左侧区域 if (anchor.x > currentRect.x) { splitRect({ x: currentRect.x, y: anchor.y, w: anchor.x - currentRect.x, h: anchor.h }, blocks) } // 切割出右侧区域 if (anchor.x + anchor.w < currentRect.x + currentRect.w) { splitRect({ x: anchor.x + anchor.w, y: anchor.y, w: currentRect.x + currentRect.w - (anchor.x + anchor.w), h: anchor.h }, blocks) } } splitRect(pageRect, redBlocks) return result }
优化提示
如果要进一步减少生成的div数量,可以在递归结束后对相邻、同宽/同高的空白矩形做合并操作,最多可以再减少30%左右的div数量。
内容的提问来源于stack exchange,提问作者Francesco Bellavita
相关产品推荐
相关产品推荐

