不能用 table 排商品卡片,因其语义错误(商品是独立内容单元而非行列数据)、响应式断裂(小屏强制横向滚动)、可访问性差(爬虫和读屏器无法识别标题/价格/按钮逻辑),且维护成本高;应改用 grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)) 配合 gap 实现真正响应式栅格。

用 display: grid 做商品卡片排版,比 flex 更稳、比 table 更语义正确,且一行代码就能适配从手机到 4K 屏。
为什么不能用 table 排商品卡片
商品不是行列对齐的参数表,而是独立可索引的内容单元。table 强行套用会导致三类硬伤:
- 小屏必须横向滚动,
overflow-x: auto没法解决语义断裂 - 爬虫和读屏器把商品当“数据格”,无法识别标题/价格/操作按钮的逻辑关系
- 加个新字段就得改
<tr> 和所有 <code><td>,JS 动态渲染时容易漏嵌套层级 <p>真实项目里看到 <code><table class="product-list">...</table>,基本可以判定是早期模板硬搬或维护停滞。grid-template-columns: repeat(auto-fill, minmax(280px, 1fr))怎么写才不翻车这是目前最实用的商品栅格声明,但漏掉一个细节就白配:
DeepBI DHTML 页面生成器下载生成可在 deepbi 沙箱 iframe 内运行或作为独立文件运行的交互式 HTML 页面,使用 `window.deepbi` JS SDK 实现数据查询、空间管理、文件浏览及用户操作。当用户提出以下需求时启用该能力: - 创建 KPI 仪表盘、数据表格、文件浏览器、成员列表、管理页面; - 明确要求“转成 dhtml”、“转译成 HTML”、“把 XX 页面转成……”、“控制台页面”、“管理后台”、“DeepBI 页面迁移”; - 提及位于 `apps/console/src/featur
立即学习“前端免费学习笔记(深入)”;
- 必须配合
gap: 16px,别用margin模拟间距——否则父子 margin 合并导致首行/末行错位 -
minmax(280px, 1fr)中的280px是最小列宽,不是固定宽;若容器宽度不足 280px × 3,它会自动缩成 2 列甚至 1 列 - IE11 不支持
auto-fill,如需兼容,得 fallback 到flex-wrap+flex-basis: 280px,并加@supports not (display: grid)包裹 - 别在父容器上设
width: 100%却忘了max-width,否则大屏下卡片被拉得太宽,图片object-fit: cover也救不回构图
卡片内部结构该用
article还是div取决于这张卡片是否具备独立语义:
- 有独立 URL、可被 RSS 抓取、需 SEO 提权 → 必须用
article,且内部至少含一个h3标题 - 只是首页轮播图下的静态推荐位,无元数据、不单独分享 →
div role="article"足够,比硬套article更干净 - 用
section包裹整组商品时,必须带h2主标题,否则大纲层级断裂,读屏器会跳过整个商品区 - JS 动态注入内容时,初始状态用
div,等数据加载完成再用replaceWith()替换为article,避免骨架屏阶段语义污染
img的srcset和sizes配错了会怎样常见现象:小屏加载 1200w 图片,首屏时间翻倍,LCP 直接超标。
-
srcset里每个图必须标w单位,比如"prod-400w.jpg 400w",漏掉w整个属性失效,浏览器退回只用src -
sizes不是像素值,而是媒体条件 + 宽度描述,例如sizes="(max-width: 768px) 100vw, 300px"—— 表示小屏占满视口,大屏固定 300px 宽 - 没写
sizes时,浏览器按默认100vw猜测,结果小屏也加载大图,这是最典型的带宽浪费点 - 别用
background-image替代img,否则爬虫抓不到图,读屏器读不出alt,srcset全白搭
真正难的不是写出这行代码,而是想清楚“这张图在页面里到底占多宽”——这个判断一旦出错,响应式就从优化变成负优化。
- 必须配合


















