使用Flexbox布局实现六边形网格时,窄屏场景下经常出现内容溢出、布局错乱的问题,很多开发者不清楚如何正确使用vh和vw单位来适配不同屏幕尺寸。

窄屏溢出的核心原因
六边形网格的实现通常依赖固定尺寸的元素配合负边距和偏移,当使用固定像素或者基于父容器百分比的单位设置元素尺寸时,窄屏下父容器宽度不足,就会导致元素被挤压溢出。很多开发者误用vh单位设置水平方向的尺寸,vh代表视口高度的百分比,在窄屏横屏场景下,视口高度小,基于vh的水平尺寸会远小于实际需求,进一步加剧溢出问题。
vh与vw单位的特性
vh和vw都是视口相对单位,二者的定义如下:
- vw:1vw等于视口宽度的1%,适合用来设置水平方向、与屏幕宽度相关的尺寸
- vh:1vh等于视口高度的1%,适合用来设置垂直方向、与屏幕高度相关的尺寸
解决窄屏溢出问题的核心就是:水平方向的尺寸优先使用vw,垂直方向尺寸如果需要关联视口再使用vh,避免用vh设置水平尺寸。
常规Flexbox六边形网格实现
先看一个容易出现窄屏溢出的基础实现代码:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
.hex-grid {
display: flex;
flex-wrap: wrap;
width: 100%;
/* 错误用法:用vh设置水平内边距,窄屏下宽度不足 */
padding: 2vh;
box-sizing: border-box;
}
.hex-item {
width: 100px;
height: 115.47px; /* 六边形高度公式:宽*√3/2*2 */
background: #4a90e2;
clip-path: polygon(50% 0%, 100% 25%, 100% 75%, 50% 100%, 0% 75%, 0% 25%);
margin: 10px;
/* 错误用法:用vh设置外边距,窄屏下边距过大导致溢出 */
margin-right: 1vh;
}
/* 偶数行偏移 */
.hex-item:nth-child(even) {
transform: translateY(57.735px);
}
</style>
</head>
<body>
<div class="hex-grid">
<div class="hex-item"></div>
<div class="hex-item"></div>
<div class="hex-item"></div>
<div class="hex-item"></div>
<div class="hex-item"></div>
<div class="hex-item"></div>
</div>
</body>
</html>
上面的代码中,内边距和外边距都使用了vh单位,在窄屏场景下,视口高度较小,这些尺寸的计算值会远小于预期,同时六边形本身用了固定像素宽度,窄屏下容器宽度不够就会直接溢出。
正确使用vh与vw修复溢出问题
调整后的代码如下,核心修改点是将水平方向的尺寸单位替换为vw,垂直方向如果不需要关联视口就不用vh:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
.hex-grid {
display: flex;
flex-wrap: wrap;
width: 100%;
/* 改用vw设置水平内边距,适配不同屏幕宽度 */
padding: 2vw;
box-sizing: border-box;
}
/* 六边形宽度基于vw设置,随屏幕宽度自适应 */
.hex-item {
width: 15vw;
/* 高度根据宽度计算,保持六边形比例 */
height: calc(15vw * 1.1547);
background: #4a90e2;
clip-path: polygon(50% 0%, 100% 25%, 100% 75%, 50% 100%, 0% 75%, 0% 25%);
/* 外边距也用vw,保证水平间距随屏幕自适应 */
margin: 1vw;
}
/* 偶数行偏移量也基于宽度计算,保持布局比例 */
.hex-item:nth-child(even) {
transform: translateY(calc(15vw * 0.57735));
}
/* 窄屏下限制最小宽度,避免元素过小 */
@media (max-width: 768px) {
.hex-item {
width: 20vw;
height: calc(20vw * 1.1547);
}
.hex-item:nth-child(even) {
transform: translateY(calc(20vw * 0.57735));
}
}
</style>
</head>
<body>
<div class="hex-grid">
<div class="hex-item"></div>
<div class="hex-item"></div>
<div class="hex-item"></div>
<div class="hex-item"></div>
<div class="hex-item"></div>
<div class="hex-item"></div>
</div>
</body>
</html>
适配要点总结
解决Flexbox六边形网格窄屏溢出问题时,关于vh和vw的使用可以遵循以下规则:
- 所有水平方向的尺寸(宽度、水平内边距、水平外边距、水平偏移量)优先使用vw单位,保证随屏幕宽度自适应
- vh单位仅用于垂直方向且需要关联视口高度的场景,不要用于设置水平方向尺寸
- 结合
calc函数和媒体查询,在窄屏下调整基础尺寸比例,避免元素过小或过大 - 不要对六边形核心尺寸使用固定像素,优先使用相对视口的相对单位
按照上述方式调整单位使用,就可以有效解决窄屏下的六边形网格溢出问题,保证布局在不同屏幕尺寸下的显示效果。