在手机端使用rem结合Flex布局实现九宫格时,经常会出现格子之间或者格子与容器边缘有多余缝隙的情况,这种问题会破坏页面的视觉一致性,需要针对性排查解决。

九宫格缝隙产生的常见原因
首先要明确缝隙出现的常见诱因,才能针对性解决:
- Flex容器的
justify-content属性设置了space-between或space-around,导致子元素之间自动分配剩余空间产生缝隙 - 子元素宽度计算时,没有考虑边框、内边距或者rem换算后的小数误差,导致实际宽度总和超过容器宽度,触发换行或挤压产生缝隙
- 子元素设置了
margin属性,或者容器设置了padding,导致额外的间距出现 - 父容器或子元素设置了
box-sizing: content-box,默认的内容宽度计算方式导致实际占位超出预期
对应的解决方法
1. 调整Flex容器属性
如果不需要子元素之间自动分配剩余空间,将justify-content设置为flex-start,避免自动产生间距:
/* 九宫格容器样式 */
.grid-container {
display: flex;
flex-wrap: wrap;
/* 避免自动分配剩余空间产生缝隙 */
justify-content: flex-start;
width: 10rem; /* 假设根元素字体大小为37.5px,对应375px手机屏幕宽度 */
margin: 0 auto;
}
2. 精确计算子元素宽度
九宫格每行3个,子元素宽度应该设置为calc(100% / 3),同时设置box-sizing: border-box让边框和内边距计入宽度,避免溢出:
.grid-item {
/* 精确计算每行3个的宽度 */
width: calc(100% / 3);
height: calc(100% / 3);
box-sizing: border-box;
/* 可选:设置内边距调整内容区域,不会额外增加宽度 */
padding: 0.2rem;
/* 避免设置margin,防止产生额外缝隙 */
/* margin: 0.1rem; 不要设置这类margin */
}
3. 处理rem换算的小数误差
rem单位在换算时可能出现小数,比如设计稿375px宽度,根字体37.5px,10rem就是375px,子元素宽度如果是3.33rem,换算后可能是124.9875px,多行累积后会出现缝隙。可以通过给子元素设置flex-shrink: 0禁止收缩,或者调整容器宽度为整数rem:
/* 根元素字体大小设置,避免换算误差 */
html {
/* 375px设计稿对应根字体37.5px,1rem=37.5px */
font-size: 37.5px;
}
.grid-item {
width: calc(100% / 3);
flex-shrink: 0; /* 禁止收缩,避免小数误差导致的宽度变化 */
}
4. 完整示例代码
下面是完整的无缝隙九宫格实现代码:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<title>无间隙九宫格</title>
<style>
html {
/* 375px设计稿根字体大小 */
font-size: 37.5px;
}
body {
margin: 0;
padding: 0;
}
.grid-container {
display: flex;
flex-wrap: wrap;
justify-content: flex-start;
width: 10rem; /* 375px */
margin: 0 auto;
border: 1px solid #eee;
}
.grid-item {
width: calc(100% / 3);
height: 3.33rem; /* 约125px */
box-sizing: border-box;
display: flex;
align-items: center;
justify-content: center;
border: 1px solid #ddd;
/* 解决边框重叠导致的视觉缝隙,使用负margin */
margin-left: -1px;
margin-top: -1px;
}
/* 第一行去掉顶部负margin */
.grid-item:nth-child(-n+3) {
margin-top: 0;
}
/* 第一列去掉左侧负margin */
.grid-item:nth-child(3n+1) {
margin-left: 0;
}
</style>
</head>
<body>
<div class="grid-container">
<div class="grid-item">格子1</div>
<div class="grid-item">格子2</div>
<div class="grid-item">格子3</div>
<div class="grid-item">格子4</div>
<div class="grid-item">格子5</div>
<div class="grid-item">格子6</div>
<div class="grid-item">格子7</div>
<div class="grid-item">格子8</div>
<div class="grid-item">格子9</div>
</div>
</body>
</html>
注意事项
如果九宫格子元素需要设置边框,建议使用负margin抵消边框带来的宽度增加,避免边框导致子元素换行产生缝隙。同时不要给子元素设置margin属性,所有间距可以通过padding在box-sizing: border-box的前提下实现,这样不会影响整体宽度计算。
另外在测试时,可以在不同尺寸的手机端查看效果,确认rem换算后的宽度是否准确,如果出现个别机型有缝隙,可以适当调整容器宽度为9.98rem这类略小的值,预留一点误差空间。