用 mPDF 生成带复杂表格的 PDF 报表时,不少人遇到过这样一种情况:某个使用了 rowspan 的单元格里放了较多文字,最终导出的文件里整张表的字体莫名其妙变小了。这其实是 mPDF 的表格自动缩放机制在起作用,它会为了把内容硬塞进页面宽度而压缩字号,而不是单纯样式问题。

一、mPDF 表格缩放的底层逻辑
mPDF 在渲染表格时,默认采用一种“自适应”思路。当表格总宽度超过页面可用宽度,或者某个跨行单元格的内容在按当前字号排版会溢出时,内核会计算一个缩放比例,把表格内所有文字的字号等比例缩小,从而保证内容不超出边界。这个逻辑对普通单元格偶尔有用,但遇到 rowspan 内容堆积,就会连累整表。
核心配置里有两个关键项:keep_table_proportions 和 autosize。前者为 true 时会保持表格各列比例但允许整体缩放,后者控制是否启用自动调整大小。很多项目直接沿用默认配置,等于默许了字体被缩小的可能。理解这两个参数的指向,是解决问题的第一步。
1.1 默认行为演示
下面这段 HTML 在 mPDF 中若不加干预,右侧 rowspan 单元格文字一多,左侧普通单元格的字也会跟着变小:
<table border="1" style="width:100%">
<tr>
<td>普通单元格</td>
<td rowspan="3">这里放了很长很长的说明文字,描述项目背景、实施细节以及后续规划,内容堆积导致 mPDF 自动缩小整表字体。</td>
</tr>
<tr><td>第二行</td></tr>
<tr><td>第三行</td></tr>
</table>
从渲染结果看,本应清晰的“普通单元格”几个字也被压扁,报表观感大打折扣。我们需要从配置与结构两个层面同时入手。
二、通过配置关闭自动缩放
最直接的方式是在初始化 mPDF 或写表格时,明确关掉自动缩放相关的开关。可以在构造实例时传入参数,也可在 CSS 中声明避免被压缩。
使用 PHP 端配置时,把 autosize 设为 0,并合理设置 keep_table_proportions 为 false,告诉内核不要为了保持比例而缩小字体。示例如下:
<?php
require_once __DIR__ . '/vendor/autoload.php';
$mpdf = new MpdfMpdf([
'autosize' => 0,
'keep_table_proportions' => false,
'default_font_size' => 12,
]);
$html = '<table border="1" style="width:100%">
<tr><td>普通单元格</td>
<td rowspan="3">较长内容放在这里,但字体不会被整体缩小</td></tr>
<tr><td>第二行</td></tr>
<tr><td>第三行</td></tr>
</table>';
$mpdf->WriteHTML($html);
$mpdf->Output();
上述代码把自动缩放完全关掉,表格将严格按设定字号输出。缺点是若内容真的太宽,可能会超出页面,因此还要配合固定列宽与分页策略。
2.1 在 CSS 中约束宽度
除了 PHP 配置,还可以在表格样式里写死列宽,降低 mPDF 触发缩放的动机。给普通列和跨行列分别指定合理百分比,避免它自行重算:
<table border="1" style="table-layout:fixed;width:100%">
<colgroup>
<col style="width:30%">
<col style="width:70%">
</colgroup>
<tr>
<td>普通单元格</td>
<td rowspan="3">通过固定布局,跨行内容再多也不会引发整表字体缩放。</td>
</tr>
<tr><td>第二行</td></tr>
<tr><td>第三行</td></tr>
</table>
table-layout:fixed 配合 colgroup 能显著减少 mPDF 的“自由发挥”。实践中这一招和关闭 autosize 叠加使用最稳。
三、结构优化:拆分 rowspan 与手动分页
当跨行单元格内容确实过多,即便不缩放也会导致单页排不下,此时应考虑拆分结构。一种思路是取消 rowspan,把长文本单独做成一行通栏,用视觉分隔代替纵向合并。
另一种做法是在长内容中间插入 mPDF 的分页标记,强制把剩余部分推到下一页,从而不让单页内出现超高单元格。示例如下:
<table border="1" style="width:100%">
<tr><td>标题</td><td>说明</td></tr>
<tr>
<td>项目A</td>
<td>前半段内容描述……</td>
</tr>
<tr><td colspan="2">分页前收尾</td></tr>
</table>
<pagebreak />
<table border="1" style="width:100%">
<tr>
<td>项目A续</td>
<td>后半段内容详细描述,避免单页 rowspan 过高。</td>
</tr>
</table>
这种写法虽多了点重复表头,但彻底规避了缩放与溢出。对于合同、审计类文档,清晰度远比节省页数重要。
四、综合建议与避坑提醒
不要迷信“mPDF 会自动帮我排好版”。凡是涉及 rowspan 且内容长度不可控的报表,都建议显式关掉 autosize,并用固定布局锁列宽。若仍出现字体变化,检查是否外层容器设了不合理百分比,或字体声明被后续样式覆盖。
最后提醒,调试时把 mPDF 的调试模式打开,能看到表格重算轨迹。结合本文的配置与结构方案,基本可确保表格因 rowspan 内容多而自动缩字的问题不再出现,输出符合预期的规范 PDF。