必须用 <table> 而非 div 或 CSS Grid,因其原生语义支持行列映射、分页控制、Excel 导出及读屏识别;需写全 <thead>/<tbody>、scope="col"/scope="row",价格列用 class="price"、等宽字体与 tabular-nums 对齐,移动端通过 data-label 堆叠实现无滚动清爽体验。

用 <table> 做价目表,清爽不靠“删边框”,靠语义清晰 + 列级控制 + 价格视觉锚点。别用 div 模拟表格,它既不清爽也不可靠。
为什么必须用 <table> 而不是 div + CSS Grid
价目表是典型的行列结构化数据:横向是套餐(基础版、专业版),纵向是功能项(存储、月费、支持)。浏览器和屏幕阅读器依赖 <table> 的原生语义自动建立“第2列是价格”“第3行是企业版”的映射关系。div 布局在 DOM 中只是扁平盒子,读屏软件听到的是“容器、容器、容器”,打印时容易跨页断行,导出 Excel 更是全挤进 A1 单元格。
- Chrome 打印预览中某一行被截成两页,第二页只剩价格没产品名 → 没
<thead>/<tbody>分离,分页逻辑失效 - 用户复制整列价格粘贴到 Excel,结果所有数字堆在同一格 → 缺少真实表格结构,JS 导出库无法解析行列
- 缩放至 125% 后价格列文字换行错位 →
div无原生列宽约束,CSS Grid 的fr单位响应不稳定
<thead> 和 <tbody> 必须写全,scope="col" 不能省
只写 <table><tr><th>基础版</th><th>专业版</th></tr><tr><td>✓</td><td>✓</td></tr></table> 是无效语义。辅助技术无法区分哪行是标题、哪行是数据,scope="col" 缺失时,屏幕阅读器不知道这个 <th> 是管整列还是仅当前单元格。
-
<thead>只放一行<tr>,每个列头用<th scope="col">,例如<th scope="col">专业版</th> -
<tbody>每个<tr>对应一款套餐,功能项用<th scope="row">标明行含义,比如<th scope="row">月费</th> - 避免
colspan/rowspan—— 它破坏列索引连续性,导致td:nth-child(2)选错列,小屏堆叠逻辑也失效
价格列怎么真正“清爽”地跳出来
清爽不是背景色+阴影,而是让用户扫一眼就锁定价格。关键在列级样式控制 + 数字排版可靠性,不是给每个 <td> 打补丁。
立即学习“前端免费学习笔记(深入)”;
- 给价格列加类名:
<td class="price">¥29.00</td>,后续 JS 或 CSS 都好定位 - CSS 用
font-variant-numeric: tabular-nums实现小数点对齐(注意 Safari 旧版不支持,但价格列对齐优先级低于可访问性) - 禁用空格对齐:
<td>¥ 99.00</td>在缩放或换字体后全乱,且复制粘贴会引入全角空格,Excel 导入失败 - 价格数字单独包裹
<strong>:<td class="price"><strong>¥29.00</strong>/月</td>,方便统一加粗、调大字号
移动端怎么做到“清爽不滚动”
横向滚动不是响应式,是妥协。清爽的移动端体验是把横向对比转为纵向堆叠阅读,每行带上下文前缀,不用左右拖拽就能看清“专业版|SSL 证书|包含”。
- 小屏用
@media (max-width: 768px),把<td>设为display: block,并配合data-label属性存列名:<td data-label="专业版">✓</td> - CSS 写
td::before { content: attr(data-label) ": "; font-weight: bold; },自动补上前缀 - 禁用
table-layout: fixed—— 它会让小屏下长文本被截断;保持默认auto,由内容撑开宽度 - 给所有
<th>和<td>加padding: 0.5rem 0.75rem,否则小屏糊成一块
最容易被忽略的是:价格列的 font-family 必须用等宽字体(如 "Consolas", "SFMono-Regular", monospace),否则 “¥99.00” 和 “¥1280.00” 就算用了 tabular-nums 也对不齐 —— 字体本身不等宽,数字宽度就不可控。



















