<p>直接用width:33.333%在Flex九宫格中易出问题,因flex-shrink默认为1,内容变化会压缩宽度,iOS Safari尤敏感;应改用flex-basis锁定尺寸,如flex:0 0 calc(33.333% - 4px)配合gap:4px,或降级用margin并清除末项间隙。</p>

为什么直接用 width: 33.333% 在 Flex 九宫格里会出问题
不是不能用,而是用了就容易在真实设备上“歪掉”或“换行错乱”。flex-shrink 默认为 1,只要子项内容(比如文字、图标)撑开或缩窄,浏览器就会按比例压缩 width 值;iOS Safari 尤其敏感。抽奖界面要求每个格子视觉上严格等宽、间距一致,哪怕偏差 1px,转盘动画停在边界时都会显得卡顿或偏移。
flex-wrap: wrap 必须配 flex-basis,而不是只靠 width
flex-basis 是 Flex 主轴上的尺寸锚点,它比 width 优先级高,且不受 flex-shrink 干扰。要锁死每行 3 个,就得让每个 .grid-item 的主轴基准是 “三分之一容器宽减去间隙”:
- 若用
gap: 4px(现代写法),写flex: 0 0 calc(33.333% - 4px)—— 注意:这里扣的是整条间隙,不是一半 - 若降级用
margin(兼容 iOS flex: 0 0 calc(33.333% - 2px),再配合margin-right: 2px; margin-bottom: 2px - 父容器必须设
display: flex; flex-wrap: wrap;,且加overflow: hidden防 margin 外扩导致横向滚动条
高度怎么稳住 1:1 且不塌陷
Flex 容器不会自动维持宽高比,height: 33.333% 在无明确父高时无效。别用 padding-top: 100% 伪元素硬凑——它依赖 position: relative + ::before,真机上可能触发重排抖动。更稳妥的做法:
- 优先用
aspect-ratio: 1(iOS 16.4+ / Chrome 88+ 支持) - 老版本 fallback:给
.grid-item设min-height: 44px(满足 iOS 点击热区最小尺寸),再加height: 0; padding-bottom: 100%+position: relative,内容层用position: absolute; inset: 0 - 必须加
box-sizing: border-box,否则padding或border会让实际尺寸超预期
点击失效、连点才触发?这不是布局问题,是 touch-action 没设
很多团队调完样式就上线,结果真机测试发现点不动——iOS 默认把短按识别为页面滑动意图。解决方法极简单但常被忽略:
立即学习“前端免费学习笔记(深入)”;
- 给每个
.grid-item加touch-action: manipulation,明确告诉系统:“这个区域只响应点击/长按,别拿去滚动” - 避免在
.grid-item内套div再绑事件,直接在 item 上用addEventListener('click', ...)或 jQuery.on('click', ...) - 禁用
user-select: none(除非真需要),它有时会干扰 touch 事件流
最麻烦的从来不是“怎么排成 3×3”,而是让每个格子在各种屏幕下尺寸精确、不塌陷、不换错行、点击响应可靠——这些细节一旦漏掉,抽奖动画停在边缘时那一帧的视觉偏差,用户立刻能感知到。


















