Перейти к содержимому
getnextpdf.com

стабильность: Экспериментальная

Вёрстка с сохранением для CSS Grid (grid-template-areas)

Подключаемое превью. Режим с сохранением по умолчанию выключен. Режим Streaming по умолчанию даёт побайтово идентичный результат сборке, которая никогда не знала о существовании этого режима. Включайте его только для документов, которым нужна настоящая сетка, и проверяйте результат.

По умолчанию рендерер однопроходный и потоковый (см. ADR-001). Сетку CSS Grid, объявленную через grid-template-areas, нельзя разместить за один прямой проход, поэтому потоковый движок выдаёт предупреждение HTML_GRID_REQUIRES_RETAINED и откатывается к блочному потоку. Режим с сохранением — это подключаемая опция, которая заменяет этот запасной вариант настоящей вёрсткой: Config::withCssLayoutMode(CssLayoutMode::Retained) направляет сетку grid-template-areas с определёнными колонками через GridLayoutEngine, который размещает дочерние элементы в их именованные ячейки.

Окно терминала
composer require nextpdf/core:^3

Режим вёрстки поставляется в пакете core. Подключаемая опция Config::withCssLayoutMode помечена @since 6.0.0. По умолчанию остаётся CssLayoutMode::Streaming.

CssLayoutMode — типизированное перечисление в Config. Streaming — это значение по умолчанию и историческое поведение; Retained подключает документ к движку сеток. Режим с сохранением держит ограниченный набор сохранённых узлов (retainedNodeBudget, по умолчанию 50,000, ограничен диапазоном [5,000, 100,000]), чтобы движок мог разрешить сетку, которую потоковый режим разрешить не может, — не отказываясь от дисциплины памяти движка.

Когда режим с сохранением включён и движок встречает сетку grid-template-areas, чьи колонки определены, он размещает сетку по-настоящему. Определённые колонки — это фиксированные длины, проценты или единицы fr, разрешённые относительно ширины содержимого. Строки переносятся автоматически. Дочерние элементы назначаются в ячейки, которые выбирают имена их областей.

ADR-001 фиксирует инвариант потоковости. Поправка от 2026-06-28 к ADR-001 добавляет исключение для подключаемого режима с сохранением: потоковое поведение по умолчанию не затрагивается и остаётся однопроходной моделью; режим с сохранением — это явно ограниченное, подключаемое исключение для случая сетки.

Граница — что размещает режим с сохранением, а что по-прежнему откатывается

Заголовок раздела «Граница — что размещает режим с сохранением, а что по-прежнему откатывается»

Режим с сохранением обрабатывает случай grid-template-areas с определёнными колонками и только его. Всё за его пределами сохраняет предупреждение HTML_GRID_REQUIRES_RETAINED и блочный запасной вариант даже при включённом режиме с сохранением:

  • grid-auto-flow: column и grid-auto-flow: dense.
  • subgrid.
  • Запросы @container.
  • Автоматические или внутренние дорожки колонок (auto, min-content, max-content).

Это отложенные слои, а не скрытые пробелы. Сетка, зависящая от одного из них, деградирует к блочному потоку и сообщает вам об этом.

Граница с отказом закрытием. Несовпадение ширины захвата и движка — измеренная ширина содержимого не согласуется с шириной, относительно которой разрешает сетку движок, — отказывает закрытием, а не выдаёт сетку со смещением. Режим с сохранением также несовместим с режимом рендеринга Safe CSS: CssRenderingMode::Safe в сочетании с CssLayoutMode::Retained вызывает IncompatibleRenderingModeException при проверке конфигурации. CssLayoutMode::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/Streaming, Retained; Auto зарезервирован (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; это пока не пригодный третий вариант.
  • Несовпадение ширины отказывает закрытием. Расхождение ширины содержимого между захватом и движком отклоняется, а не рендерится неверно.

Режим с сохранением держит ограниченный набор узлов, а не полное дерево документа; retainedNodeBudget (по умолчанию 50,000) ограничивает его. Размещение сетки линейно по числу узлов и ячеек. Постраничный performance_budget (wall_ms: 1500, peak_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; сквозное соответствие здесь не заявляется. Текст стандартов не воспроизводится.