跳转到内容
getnextpdf.com

稳定性: 实验性

面向 CSS Grid 的保留模式布局(grid-template-areas)

可选启用的预览。 保留模式默认关闭。默认的 Streaming 模式与一个从不知道该模式存在的构建字节完全一致。只为那些确实需要真正网格的文档开启它,并验证结果。

默认情况下,渲染器是单遍且流式的(参见 ADR-001)。一个用 grid-template-areas 声明的 CSS Grid 无法在一次前向遍历中放置,因此流式引擎会发出一个 HTML_GRID_REQUIRES_RETAINED 警告并回退到块流。保留模式就是用真正的布局取代该回退的可选开关:Config::withCssLayoutMode(CssLayoutMode::Retained) 会把一个确定列的 grid-template-areas 网格路由给 GridLayoutEngine,由它把子元素放入它们的命名单元格中。

Terminal window
composer require nextpdf/core:^3

该布局模式随核心包一起分发。Config::withCssLayoutMode 这个可选开关是 @since 6.0.0。默认仍为 CssLayoutMode::Streaming

CssLayoutModeConfig 上的一个带类型枚举。Streaming 是默认值,也是一直以来的行为;Retained 把一份文档接入网格引擎。保留模式持有一个有界的保留节点集(retainedNodeBudget,默认 50,000,被钳制在 [5,000, 100,000]),使引擎能解析流式无法处理的网格——同时不放弃引擎的内存纪律。

当保留模式开启、且引擎遇到一个列为确定的 grid-template-areas 网格时,它会真正地把网格排布出来。确定列是固定长度、百分比,或针对内容宽度解析的 fr 单位。行会自动流动。子元素被指派到其区域名所选择的单元格中。

ADR-001 记录了流式不变量。对 ADR-001 的 2026-06-28 修订增加了一个保留-可选启用的豁免:流式默认未被触动,仍然是单遍模型;保留模式是针对网格情形的、显式有界的可选启用例外。

边界——保留模式排布什么,以及什么仍然回退

标题为“边界——保留模式排布什么,以及什么仍然回退”的章节

保留模式处理确定列的 grid-template-areas 情形,且仅此一种。即便保留模式开启,其外的一切仍保留 HTML_GRID_REQUIRES_RETAINED 警告与块回退:

  • grid-auto-flow: columngrid-auto-flow: dense
  • subgrid
  • @container 查询。
  • 自动或内在的列轨道(automin-contentmax-content)。

这些是被推迟的切片,而非沉默的缺口。一个依赖其中之一的网格会降级为块流并明确告知你。

Fail-closed 边界。 一处捕获宽度与引擎宽度不匹配——所测内容宽度与网格引擎据以解析的宽度不一致——会 fail closed,而不是产出一个错位的网格。保留模式还与 Safe CSS 渲染模式不兼容:CssRenderingMode::SafeCssLayoutMode::Retained 组合时,会在配置校验阶段抛出 IncompatibleRenderingModeExceptionCssLayoutMode::Auto 为保留项,会抛出 NotImplementedException

符号位置角色
Config::withCssLayoutMode(CssLayoutMode $mode): selfsrc/Core/Config.php把一份文档接入 Streaming(默认)或 Retained 布局。
Config::withRetainedNodeBudget(int $budget): selfsrc/Core/Config.php限定保留节点集([5,000, 100,000],默认 50,000)。
Config::isRetainedMode(): boolsrc/Core/Config.php报告该文档是否处于保留模式。
CssLayoutModesrc/Core/StreamingRetainedAuto 为保留项(NotImplementedException)。
GridLayoutEnginesrc/Html/保留模式的网格放置引擎。
IncompatibleRenderingModeExceptionsrc/Exception/当 Safe CSS 模式与保留模式组合时抛出。
<?php
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use NextPDF\Core\Config;
use NextPDF\Core\CssLayoutMode;
use NextPDF\Core\Document;
$config = (new Config())->withCssLayoutMode(CssLayoutMode::Retained);
$doc = Document::createStandalone($config);
$doc->addPage();
$doc->writeHtml(
'<style>'
. '.dashboard { display: grid; grid-template-columns: 1fr 2fr;'
. ' grid-template-areas: "sidebar main"; }'
. '.sidebar { grid-area: sidebar; } .main { grid-area: main; }'
. '</style>'
. '<div class="dashboard">'
. ' <div class="sidebar">Navigation</div>'
. ' <div class="main">Report content…</div>'
. '</div>',
);
$doc->save(__DIR__ . '/grid.pdf');

在配置阶段检测不兼容模式的情形,并回读当前生效的模式,使路径明确。

<?php
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use NextPDF\Core\Config;
use NextPDF\Core\CssLayoutMode;
use NextPDF\Core\Document;
use NextPDF\Exception\IncompatibleRenderingModeException;
try {
$config = (new Config())
->withCssLayoutMode(CssLayoutMode::Retained)
->withRetainedNodeBudget(75_000);
$config->validate();
} catch (IncompatibleRenderingModeException $e) {
// Safe CSS mode and retained mode cannot combine. Choose one.
throw $e;
}
$doc = Document::createStandalone($config);
assert($config->isRetainedMode());
$doc->addPage();
$doc->writeHtml($gridHtml);
$doc->save($out);
// A grid that needs a deferred feature (column auto-flow, subgrid, @container,
// or intrinsic columns) still emits HTML_GRID_REQUIRES_RETAINED and falls back
// to block flow. Inspect the advisory channel.
  • Streaming 仍为默认,且字节一致。 保留模式只为你显式接入的那份文档改变输出。
  • 仅限确定列的 grid-template-areas 列自动流动、密集打包、subgrid、@container 与内在列仍保留 HTML_GRID_REQUIRES_RETAINED 警告与块回退。
  • Safe 模式互斥。 CssRenderingMode::Safe 加上 CssLayoutMode::Retained 会抛出 IncompatibleRenderingModeException
  • Auto 为保留项。 CssLayoutMode::Auto 会抛出 NotImplementedException;它目前还不是一个可用的第三选项。
  • 宽度不匹配会 fail closed。 一处捕获宽度与引擎内容宽度的不一致会被拒绝,而不是渲染错误。

保留模式持有的是一个有界的节点集,而非一棵完整的文档树;retainedNodeBudget(默认 50,000)为其设上限。网格放置在节点数与单元格数上呈线性。逐页的 performance_budgetwall_ms: 1500peak_mb: 64)适用;当把节点预算朝其 100,000 上限提高时,大型网格应把该预算记在心上。

保留模式不会扩大输入面。HTML 安全策略、CSS 属性允许清单与解析器上限均原样适用。保留节点预算本身就是一道资源耗尽边界:它为引擎为单份文档所持有的结构量设上限。

主张标准条款
grid-template-areas 为网格单元格命名;命名区域放置项目。W3C CSS Grid Layout Module Level 1§7.3
显式的固定、百分比与 fr 轨道针对内容宽度确定尺寸。W3C CSS Grid Layout Module Level 1§7.2

这是一个确定列 grid-template-areas 子集的预览实现。逐属性的已验证状态记录在 CSS 支持矩阵中;此处不主张任何端到端符合性。未重制任何标准原文。