display: flex 更稳妥,因 iOS Safari 15.6 以下及微信 WebView 存在 Grid 隐式行高塌陷、gap 不生效等兼容问题,一线电商如小米商城、京东 M 站仍主用 Flex 实现商品列表。

移动端商品列表用 Flex 还是 Grid?
直接说结论:display: flex 更稳妥,display: grid 在 iOS Safari 15.6 以下版本存在隐式行高塌陷、gap 不生效等兼容问题,尤其在微信 WebView(基于旧版 X5 内核)里容易导致卡片错位。小米商城、京东 M 站等一线电商的列表层至今仍以 flex 为主轴布局,不是技术保守,而是实测过真机兼容性。
实操建议:
- 主容器设
display: flex+flex-wrap: wrap,子项用flex: 0 0 calc(50% - 8px)实现双列(留出间距) - 避免用
grid-template-columns: repeat(auto-fill, minmax(…))做响应式列数,它在部分 Android 10 WebView 中会忽略minmax下限 - 若必须用 Grid,加降级:先写
display: flex,再用@supports (display: grid)覆盖
商品卡片内部结构怎么写才不卡顿?
卡顿往往不是 JS 引起的,而是 DOM 层级过深 + 无节制的 box-shadow + 图片未 lazyload 导致的重排重绘。小米商城商品卡片控制在 6 层以内(article > a > div > img + div > h3 + p),且关键节点都带语义化标签。
实操建议:
- 外层用
article标明独立商品单元,方便后续无障碍阅读和 SEO 抓取 -
img必须带loading="lazy"和明确的width/height,否则 iOS Safari 会触发 layout thrashing - 价格、标题等文本区域禁用
box-shadow,改用border或半透背景模拟层次感 - hover 效果在移动端统一转为
:active,并加touch-action: manipulation提升响应速度
列表滚动时图片闪烁或白屏怎么办?
这是 iOS Safari 的经典 bug:当 img 处于 viewport 边缘、且父容器有 transform 或 will-change 时,GPU 渲染层切换失败,表现为闪白或加载中断。微信内嵌浏览器复现率更高。
实操建议:
- 移除所有对商品卡片容器的
transform: translateZ(0)强制 GPU 加速(已过时,反而有害) - 用
contain: layout style paint代替,能明确告诉浏览器“这个卡片的渲染不会影响外部” - 图片加载完成前,用
background-color占位(如浅灰),而不是透明底色 - 若用
IntersectionObserver做懒加载,监听阈值设为0.1而非0,给渲染留出缓冲帧
如何让列表在不同机型上保持一致的视觉密度?
单纯靠媒体查询调 font-size 或 padding 不够——iPhone SE 和 Pixel 4 的物理像素密度差近 2 倍,但 viewport 缩放逻辑不同,导致“看起来一样大”的元素实际触摸热区可能小到误触。
实操建议:
- 基础字号用
rem,但根字体大小按设备像素比动态设:document.documentElement.style.fontSize = `${window.devicePixelRatio * 16}px` - 卡片内边距统一用
px(如padding: 12px),避免 rem 在高 DPR 设备下被过度放大 - 关键点击区域(如“加入购物车”按钮)最小尺寸设为
44px × 44px,这是 iOS 人机接口指南硬性要求 - 禁用
user-scalable=no,否则 iPhone 上双指缩放会破坏你精心设计的密度
真实项目里最常被忽略的,是把“列表”当成纯展示容器,而没把它当作一个可被屏幕阅读器逐项导航、可被搜索引擎识别为商品集合、可被 PWA 缓存策略单独管理的独立语义单元。写完 ul 和 li 后,多问一句:如果此刻断网,用户还能不能靠键盘 Tab 键顺畅浏览每件商品?
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











