必须用table而非div布局,因其语义明确、读屏器解析一致;模拟表格会退化为无关系文字流,无法传达行列归属,且仅table支持无障碍、打印及pdf导出。

为什么必须用 <table> 而不是 <code><div> 布局
<p>浏览器和读屏器对 <code><table> 的解析是固化且一致的;<code><div> 模拟表格会让结构退化成无关系的文字流。比如用户用 VoiceOver 朗读时,<code><div class="cell">✅ 完全无法传达“这个对勾属于‘SSO 集成’列、‘企业版’行”。真正要表达“条目 × 方案”的二维关系,<code><table> 是唯一语义正确、可访问、可打印、可导出 PDF 的选择。
<h3><code><th scope="col"> 和 <code><th scope="row"> 怎么分才不翻车
<p>核心判断标准:它是否在定义行列含义?</p>
<ul><li>首行商品/方案名称(如“基础版”“专业版”)→ <code><th scope="col">
<li>首列参数/功能项(如“并发连接数”“5G 支持”)→ <code><th scope="row">
<li>中间所有交叉数据格(✔️/❌/文字说明/链接)→ 全部用 <code><td>,哪怕内容带图标或按钮
<li>序号列、操作列(如“试用”“对比”)→ 也是数据,用 <code><td>,别手贱写成 <code><th>
<p>漏掉 <code>scope 属性会导致屏幕阅读器无法关联单元格与表头,这是无障碍合规硬性要求,不是“可选优化”。
如何用 colspan 和 rowspan 实现 CLEAR 多级表头
colspan 和 rowspan 实现 CLEAR 多级表头CLEAR 不是 CSS 类名,而是指“Category–Label–Entry–Row”四级逻辑结构:大类(如“网络”)→ 子类(如“4G”“5G”)→ 参数(如“频段支持”)→ 数据(各产品值)。只有这两类场景才该用合并:
- 多级表头:外层
<tr> 中的 <code><th colspan="2"> 写“网络”,内层 <code><tr> 用两个 <code><th scope="col"> 写“4G 频段”“5G 频段” <li>跨行说明:某参数组(如“摄像头”)下含多个子项,主标题用 <code><th rowspan="3">,后续三行对应子项用普通 <code><th scope="row"> <li>其他情况一律禁用 <code>colspan/rowspan—— 容易错列、打印截断、Safari 渲染异常 - 用
td::before { content: attr(data-label); }补列名,前提是每个<td> 都有 <code>data-label="专业版"属性 - 每行变成独立区块,内部用
flex或grid垂直堆叠“参数名 + 两列值”,顺序必须是“条目名 → 方案A值 → 方案B值”,否则读屏器会错乱 - 绝对不要用
transform或position: absolute移动单元格——焦点顺序和 DOM 顺序彻底脱钩
rowspan 值必须严格等于它跨越的 <td> 行数,且后续行中对应列位置必须跳过,否则浏览器会自动补空 <code><td>,造成整行偏移。
<h3>移动端怎么避免横向滚动还能保持语义完整</h3>
<p>给 <code><table> 包 <code><div style="overflow-x: auto"> 是半残方案:用户得手动拖、键盘焦点失效、缩放后文字糊成一片。真正可用的是 CSS 主导的 DOM 重排:
<ul><li>小屏下(<code>max-width: 768px)把每个 <tr> 设为 <code>display: block
最易被忽略的一点:重排后的每个 <tr> 区块,必须保留原始 <code><th scope="row"> 的语义文本,不能只靠伪元素撑起可访问性。否则 JS 动态填充数据时,<code>aria-labelledby 就断了。











