如何避免窄屏上Flexbox六边形网格元素溢出?
窄屏(手机分辨率)下Flexbox六边形网格无法居中且溢出容器的解决问题
问题描述
在窄屏(手机分辨率)下,Flexbox布局的六边形元素无法居中,且会溢出Flex容器。希望整个六边形网格能自动缩小适配窄屏,而非从屏幕侧边溢出。
- 当前效果:六边形网格在手机屏幕上横向溢出,无法完全显示,也未居中
- 预期效果:六边形网格完整适配手机屏幕宽度,居中显示,所有六边形均在可视范围内
代码片段
JavaScript
function renderHexGrid() { let hexArray = [ ['v', 'v', 'v', '_', '_', '_', 'v', 'v', 'v'], ['v', '_', '_', '_', '_', '_', '_', '_', 'v'], ['_', '_', '_', '_', '_', '_', '_', '_', '_'], ['_', '_', '_', '_', '_', '_', '_', '_', '_'], ['_', '_', '_', '_', '_', '_', '_', '_', '_'], ['_', '_', '_', '_', '_', '_', '_', '_', '_'], ['_', '_', '_', '_', '_', '_', '_', '_', '_'], ['_', '_', '_', '_', '_', '_', '_', '_', '_'], ['_', '_', '_', '_', '_', '_', '_', '_', '_'], ['v', 'v', '_', '_', '_', '_', '_', 'v', 'v'], ['v', 'v', 'v', 'v', '_', 'v', 'v', 'v', 'v'] ] const hexWidth = 7 const hexHeight = 6 const hexGrid = document.getElementById("hex-grid") for (let i = 0; i < hexArray.length; i++) { let hexRow = document.createElement("div") hexRow.style.display = "flex" hexRow.style.justifyContent = "center" for (let j = 0; j < hexArray[i].length; j++) { if (hexArray[i][j] != 'v') { let hex = document.createElement("div") hex.style.display = "flex"; hex.style.justifyContent = "center" hex.style.alignItems = "center" if (j % 2 == 0) { hex.style.transform = "translateY(-" + hexHeight / 2 + "vh)" hex.style.backgroundColor = "red" } else { hex.style.backgroundColor = "blue" } if (i % 2 == 0) { hex.style.opacity = 0.5 } hex.style.height = hexHeight + "vh" hex.style.width = hexWidth + "vh" hex.textContent = i + ";" + j hex.color = "black" hex.style.marginLeft = "-" + hexWidth / 8 + "vh" hex.style.marginRight = "-" + hexWidth / 8 + "vh" hex.style.clipPath = "polygon(25% 0%, 75% 0%, 100% 50%, 75% 100%, 25% 100%, 0% 50%)" hexRow.appendChild(hex); } } hexGrid.appendChild(hexRow); } } renderHexGrid()
CSS
* { margin: 0; padding: 0; } body { margin: 5%; width: 90%; min-height: 90vh; background-color: rgb(255, 255, 255); display: flex; align-items: center; justify-content: center; }
HTML
<div id="hex-grid"></div>
解决方案
问题根源
当前使用vh(视口高度)作为六边形尺寸单位,窄屏场景下横向宽度无法自动适配视口宽度,导致总宽度溢出;同时未给网格容器设置约束,也缺乏响应式缩放逻辑。
具体修改步骤
1. 优化容器约束(CSS)
给网格容器添加宽度限制,确保不会溢出视口,同时修正盒模型计算逻辑:
* { margin: 0; padding: 0; box-sizing: border-box; /* 确保margin/padding不额外占用宽度 */ } body { min-height: 100vh; padding: 5%; /* 用padding替代margin,避免容器偏移 */ background-color: rgb(255, 255, 255); display: flex; align-items: center; justify-content: center; } #hex-grid { width: 100%; max-width: 100%; display: flex; flex-direction: column; align-items: center; gap: calc(var(--hex-height) / 2); /* 匹配六边形垂直偏移间距 */ }
2. 动态计算响应式尺寸(JavaScript)
改用vw(视口宽度)作为尺寸单位,根据每行六边形数量自动计算大小,添加窗口 resize 监听保证适配性:
function renderHexGrid() { let hexArray = [ ['v', 'v', 'v', '_', '_', '_', 'v', 'v', 'v'], ['v', '_', '_', '_', '_', '_', '_', '_', 'v'], ['_', '_', '_', '_', '_', '_', '_', '_', '_'], ['_', '_', '_', '_', '_', '_', '_', '_', '_'], ['_', '_', '_', '_', '_', '_', '_', '_', '_'], ['_', '_', '_', '_', '_', '_', '_', '_', '_'], ['_', '_', '_', '_', '_', '_', '_', '_', '_'], ['_', '_', '_', '_', '_', '_', '_', '_', '_'], ['_', '_', '_', '_', '_', '_', '_', '_', '_'], ['v', 'v', '_', '_', '_', '_', '_', 'v', 'v'], ['v', 'v', 'v', 'v', '_', 'v', 'v', 'v', 'v'] ]; // 计算每行最多的六边形数量 const maxHexPerRow = Math.max(...hexArray.map(row => row.filter(item => item !== 'v').length)); // 基于视口宽度动态计算六边形尺寸,留出间隙 const hexWidth = Math.floor((90 / maxHexPerRow) * 0.8); const hexHeight = Math.floor(hexWidth * 0.857); // 保持6:7的六边形宽高比 // 设置CSS变量统一管理尺寸 document.documentElement.style.setProperty('--hex-width', `${hexWidth}vw`); document.documentElement.style.setProperty('--hex-height', `${hexHeight}vw`); const hexGrid = document.getElementById("hex-grid"); hexGrid.innerHTML = ''; // 清空容器避免重复渲染 for (let i = 0; i < hexArray.length; i++) { let hexRow = document.createElement("div"); hexRow.style.display = "flex"; hexRow.style.justifyContent = "center"; hexRow.style.width = "100%"; // 约束行宽度不超过父容器 for (let j = 0; j < hexArray[i].length; j++) { if (hexArray[i][j] != 'v') { let hex = document.createElement("div"); hex.style.display = "flex"; hex.style.justifyContent = "center"; hex.style.alignItems = "center"; hex.style.color = "black"; // 修正原代码无效的color设置 if (j % 2 == 0) { hex.style.transform = `translateY(-${hexHeight / 2}vw)`; hex.style.backgroundColor = "red"; } else { hex.style.backgroundColor = "blue"; } if (i % 2 == 0) { hex.style.opacity = 0.5; } hex.style.height = `var(--hex-height)`; hex.style.width = `var(--hex-width)`; hex.textContent = `${i};${j}`; // 基于当前宽度比例设置重叠margin hex.style.marginLeft = `-${hexWidth * 0.125}vw`; hex.style.marginRight = `-${hexWidth * 0.125}vw`; hex.style.clipPath = "polygon(25% 0%, 75% 0%, 100% 50%, 75% 100%, 25% 100%, 0% 50%)"; hexRow.appendChild(hex); } } hexGrid.appendChild(hexRow); } } // 监听窗口大小变化,重新渲染适配 window.addEventListener('resize', renderHexGrid); renderHexGrid();
3. 关键修改说明
- 单位切换:从
vh改为vw,优先适配横向视口宽度,避免窄屏溢出; - 动态尺寸:根据每行六边形数量自动计算尺寸,确保总宽度不超过屏幕;
- 容器约束:给
#hex-grid设置宽度限制,保证网格不会超出父容器; - 响应式适配:添加窗口 resize 监听,屏幕尺寸变化时自动重新渲染;
- 样式修复:修正原代码中无效的文字颜色设置。
内容的提问来源于stack exchange,提问作者Snakučipi
相关产品推荐
相关产品推荐

