aspect-ratio 是关键,因它使容器自动维持正方形比例,图片设 width:100%;height:100% 即可等比填充;但微信小程序基础库需 ≥2.21.0 才支持,旧版须降级 fallback。

直接用 flex + aspect-ratio + image mode="aspectFill" 就能实现自动缩放的九宫格,不需要 JS 计算宽高或监听 resize —— 但前提是你的基础库版本够新,且必须处理 fallback。
为什么 aspect-ratio 是关键,但不能无脑用
现代浏览器和微信小程序基础库 ≥ 2.21.0 支持 aspect-ratio: 1 / 1,它能让容器自动维持正方形比例,图片再设 width: 100%; height: 100% 就自然等比缩放填充。但问题在于:
- 微信小程序基础库 aspect-ratio,导致容器高度塌陷,图片被压扁或溢出
- H5 端 Safari 15.4 以下不支持,部分旧版 Chrome 需加
-webkit-aspect-ratio - uni-app 编译时不会自动补前缀,得自己写
实操建议:只在明确支持的环境启用 aspect-ratio,其余场景回退到 padding-bottom 方案(即用伪元素撑高)。
image 的 mode 必须选对,否则“自动缩放”等于白搭
九宫格里图片尺寸差异大,mode 错一个,不是裁掉人脸就是留黑边破坏网格感:
-
aspectFill:最稳选择,等比缩放后居中裁剪,填满且无拉伸,但需配合服务端封面裁剪 URL(避免前端硬裁关键内容) -
widthFix:宽度铺满、高度自适应,适合横图多的场景,但竖图会太小,视觉失衡 -
scaleToFill:禁用!强制拉伸,文字/人像类图一眼失真 -
aspectFit:等比缩放到完全显示,但四周留白——九宫格里直接破坏对齐,慎用
统一用 mode="aspectFill",再让后端返回已裁好封面的缩略图 URL,比前端拼 object-fit 或 canvas 更可控。
父容器和子项的 flex 布局必须带防崩细节
漏掉任意一项,iOS 微信或低端安卓机上就会错行、溢出、最后一行只剩一个:
- 父容器必须显式声明
display: flex; flex-wrap: wrap;—— 不写flex-wrap,所有子项强行挤一行 - 子项用
flex: 0 0 calc(33.333% - 2 * 10rpx),而不是width: 33.333%,显式扣掉左右 padding,避免box-sizing失效导致总宽超 100% - 必须加
box-sizing: border-box,否则 padding 会撑出实际宽度,三列变两列,且只在部分安卓机复现,极难定位 - 间隙统一用
padding(父容器padding: 0 10rpx+ 子项padding: 16rpx 10rpx),别用margin,防止 margin 折叠或跨端计算偏差
数据长度不是 3 的倍数时,补空逻辑不能偷懒
后端返回 7 条、8 条、11 条是常态,不处理会导致最后一行缺格子、网格断裂:
- 补空必须用真实对象,比如
{ src: '', text: '' },不能是null或undefined,否则v-for渲染报错 - 补空逻辑写在
computed里:gridList() { const padded = [...this.rawList]; while (padded.length % 3) padded.push({ src: '', text: '' }); return padded; } - 若不想显示空格子,加
v-if="item.src",但要同步把子项宽度改成calc(100% / 3),并确保父容器仍带flex-wrap
真正容易被忽略的是:补空后没清掉空项的点击事件绑定,结果点空白区域也触发跳转 —— 记得在 @click 里加 v-if 判断或前置 guard。


















