
本文介绍一种实用方法,通过预估行数控制 mpdf 输出内容高度,确保列表严格限制在单页内;当内容即将超出页面剩余空间时,自动截断并以“...”替代后续内容,避免分页。
本文介绍一种实用方法,通过预估行数控制 mpdf 输出内容高度,确保列表严格限制在单页内;当内容即将超出页面剩余空间时,自动截断并以“...”替代后续内容,避免分页。
在使用 mPDF 生成 PDF 报表时,常遇到动态列表(如订单明细、日志条目)因长度不可控而自然跨页的问题。但某些场景(如预览缩略页、票据打印、嵌入式报表)要求强制单页输出——超出部分不能分页,而应优雅截断并提示用户内容被省略。
mPDF 本身不提供“禁止分页 + 自动截断”的内置指令,因此需采用基于行高估算的主动截断策略。核心思路是:在生成 HTML 内容前,模拟排版逻辑,动态统计当前已占用行数,并在接近页面可用行数上限时提前终止循环,追加省略标识。
✅ 实现步骤与关键要点
-
确定单页可用行数(需实测校准)
行数 ≠ 像素高度,而是由字体、字号、行高、页边距、页眉页脚共同决定。建议:- 创建最小测试模板(仅含基础 CSS:body { font-family: sans-serif; font-size: 10pt; line-height: 1.4; })
- 用固定高度容器(如 )模拟 A4 可用区域
- 手动填充 10/20/30 行纯文本,导出 PDF 观察实际换行位置
- 推荐起始值:25–35 行(10pt 字体、标准边距下常见)
按字符长度粗略估算行占用
单行能容纳的字符数 ≈ 可用宽度(px) / 平均字符宽度(px)。若使用等宽字体可精确计算;否则按经验阈值近似:普通中文字体(如 dejavusans)下,10pt 时单行约容纳 80–120 字符
-
超长行会自动折行,需额外计数:
$single_line_limit = 100; // 根据实测调整 $lines_used = 0; foreach ($data as $line) { $lines_used++; // 默认占 1 行 // 折行补偿:每超限 100 字符,+1 行(支持最多 3 行) $extra_lines = (int) floor(strlen($line) / $single_line_limit); $lines_used += min($extra_lines, 2); // 最多再加 2 行(即总占 3 行) if ($lines_used > $max_allowed_lines) { break; } $html .= '<div class="list-item">' . htmlspecialchars($line) . '</div>'; }
添加省略标识并闭合结构
截断后务必追加视觉提示,增强用户体验:if ($lines_used >= $max_allowed_lines && count($data) > $n) { $html .= '<div class="ellipsis">⋯</div>'; // 或使用 … } $html .= '</div>'; // 关闭外层容器完整示例(含 CSS 优化)
$mpdf = new \Mpdf\Mpdf([ 'mode' => 'utf-8', 'format' => 'A4', 'margin_top' => 20, 'margin_bottom' => 15, 'margin_left' => 15, 'margin_right' => 15, ]); $max_allowed_lines = 28; // 经实测确认 $single_line_limit = 95; $html = '<div class="list-container" style="font-size:10pt; line-height:1.4;">'; $lines_used = 0; $n = 0; foreach ($data as $line) { $n++; $lines_used++; $len = mb_strlen($line, 'UTF-8'); // 中文按字数估算(更准确),英文按字符 $est_lines = (int) ceil($len / $single_line_limit); $lines_used += max(0, $est_lines - 1); if ($lines_used > $max_allowed_lines) { break; } $html .= '<div class="list-item" style="margin: 2px 0;">' . htmlspecialchars($line, ENT_QUOTES, 'UTF-8') . '</div>'; } if ($n < count($data)) { $html .= '<div class="ellipsis" style="color:#999; font-style:italic;">⋯ ' . (count($data) - $n) . ' more items</div>'; } $html .= '</div>'; $mpdf->WriteHTML($html); $mpdf->Output();⚠️ 注意事项
- 避免依赖 page-break-inside: avoid:该 CSS 在 mPDF 中支持有限,无法阻止内容溢出到新页,仅影响块级元素内部断行。
- 慎用 overflow: hidden:PDF 渲染不支持像素级裁剪,该样式无效。
- 动态内容需重测阈值:更换字体、增大字号或添加图标后,必须重新校准 $max_allowed_lines 和 $single_line_limit。
- 进阶方案(可选):若精度要求极高,可结合 mPDF::getPageSize() 获取可用高度(单位 mm),再用 mPDF::GetStringHeight() 计算单行像素高度,实现像素级截断——但开发成本显著上升,多数业务场景中行数估算已足够可靠。
通过以上方法,你无需修改 mPDF 底层逻辑,即可稳定实现单页强制截断,兼顾开发效率与输出可靠性。


















