stabiliteit: Experimenteel
Retained-mode lay-out voor CSS Grid (grid-template-areas)
In een oogopslag
Sectie met titel “In een oogopslag”Opt-in preview. Retained-modus staat standaard uit. De standaard
Streaming-modus is byte-identiek aan een build die deze modus nooit heeft gekend. Zet hem alleen aan voor de documenten die een echt grid nodig hebben, en valideer het resultaat.
Standaard is de renderer single-pass en streaming (zie ADR-001).
Een CSS Grid gedeclareerd met grid-template-areas kan niet in één voorwaartse
pass worden geplaatst, dus geeft de streaming-engine een
HTML_GRID_REQUIRES_RETAINED-waarschuwing af en valt terug op blokflow.
Retained-modus is de opt-in die die terugval vervangt door een echte lay-out:
Config::withCssLayoutMode(CssLayoutMode::Retained) routeert een
grid-template-areas-grid met definite columns via de GridLayoutEngine, die
kinderen in hun named cells plaatst.
Installeren
Sectie met titel “Installeren”composer require nextpdf/core:^3De lay-outmodus wordt meegeleverd in het core-pakket. De
Config::withCssLayoutMode-opt-in is @since 6.0.0. De standaard blijft
CssLayoutMode::Streaming.
Conceptueel overzicht
Sectie met titel “Conceptueel overzicht”CssLayoutMode is een getypeerde enum op Config. Streaming is de standaard en
het historische gedrag; Retained schakelt een document in voor de grid-engine.
Retained-modus houdt een begrensde behouden node-set vast (de retainedNodeBudget,
standaard 50,000, geklemd op [5,000, 100,000]) zodat de engine een grid kan
oplossen dat streaming niet kan — zonder de geheugendiscipline van de engine los te
laten.
Wanneer retained-modus aan staat en de engine een grid-template-areas-grid
tegenkomt waarvan de kolommen definite zijn, maakt hij het grid echt op. Definite
columns zijn vaste lengtes, percentages of fr-eenheden opgelost tegen de
contentbreedte. Rijen stromen automatisch. Kinderen worden toegewezen aan de cellen
die hun area-namen selecteren.
ADR-001 legt het streaminginvariant vast. Het amendement van 2026-06-28 op ADR-001 voegt een retained-opt-in-uitzondering toe: de streamingstandaard blijft onaangetast en behoudt het single-pass-model; retained-modus is een expliciet begrensde, opt-in-uitzondering voor het grid-geval.
Grens — wat retained-modus opmaakt, en wat nog terugvalt
Sectie met titel “Grens — wat retained-modus opmaakt, en wat nog terugvalt”Retained-modus handelt het grid-template-areas-geval met definite columns af, en
alleen dat geval. Alles daarbuiten behoudt de
HTML_GRID_REQUIRES_RETAINED-waarschuwing en de blokterugval, zelfs met
retained-modus aan:
grid-auto-flow: columnengrid-auto-flow: dense.subgrid.@container-query’s.- Auto- of intrinsieke kolomtracks (
auto,min-content,max-content).
Dit zijn uitgestelde delen, geen stille leemtes. Een grid dat van een ervan afhangt, degradeert naar blokflow en laat je dat weten.
Fail-closed-grens. Een mismatch tussen vastlegging en engine in de breedte — de
gemeten contentbreedte die niet overeenkomt met de breedte waartegen de grid-engine
oplost — faalt gesloten in plaats van een verkeerd geplaatst grid te produceren.
Retained-modus is ook incompatibel met de Safe CSS-renderingmodus:
CssRenderingMode::Safe gecombineerd met CssLayoutMode::Retained werpt
IncompatibleRenderingModeException bij de configuratievalidatie.
CssLayoutMode::Auto is gereserveerd en werpt NotImplementedException.
API-oppervlak
Sectie met titel “API-oppervlak”| Symbool | Locatie | Rol |
|---|---|---|
Config::withCssLayoutMode(CssLayoutMode $mode): self | src/Core/Config.php | Schakelt een document in voor Streaming (standaard) of Retained lay-out. |
Config::withRetainedNodeBudget(int $budget): self | src/Core/Config.php | Begrenst de behouden node-set ([5,000, 100,000], standaard 50,000). |
Config::isRetainedMode(): bool | src/Core/Config.php | Meldt of het document in retained-modus is. |
CssLayoutMode | src/Core/ | Streaming, Retained; Auto gereserveerd (NotImplementedException). |
GridLayoutEngine | src/Html/ | De behouden grid-plaatsingsengine. |
IncompatibleRenderingModeException | src/Exception/ | Gegooid wanneer de Safe CSS-modus met retained-modus wordt gecombineerd. |
Codevoorbeeld — Snelle start
Sectie met titel “Codevoorbeeld — Snelle start”<?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');Codevoorbeeld — Productie
Sectie met titel “Codevoorbeeld — Productie”Detecteer het incompatibele-modusgeval op configuratietijd, en lees de actieve modus terug zodat het pad expliciet is.
<?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.Randgevallen en valkuilen
Sectie met titel “Randgevallen en valkuilen”- Streaming blijft de standaard en is byte-identiek. Retained-modus verandert de uitvoer alleen voor het document waarvoor je het inschakelt.
- Alleen
grid-template-areasmet definite columns. Kolom-auto-flow, dense packing, subgrid,@containeren intrinsieke kolommen behouden deHTML_GRID_REQUIRES_RETAINED-waarschuwing en de blokterugval. - Safe mode is wederzijds uitsluitend.
CssRenderingMode::SafeplusCssLayoutMode::RetainedgooitIncompatibleRenderingModeException. Autois gereserveerd.CssLayoutMode::AutowerptNotImplementedException; het is nog geen bruikbare derde optie.- Breedtemismatch faalt gesloten. Een onenigheid in de contentbreedte tussen vastlegging en engine wordt geweigerd, niet verkeerd weergegeven.
Prestaties
Sectie met titel “Prestaties”Retained-modus houdt een begrensde node-set vast in plaats van een volledige
documentboom; de retainedNodeBudget (standaard 50,000) begrenst die.
Grid-plaatsing is lineair in het node- en celaantal. Het performance_budget per
pagina (wall_ms: 1500, peak_mb: 64) geldt; grote grids moeten het budget in
gedachten houden bij het verhogen van het node-budget richting het plafond van
100,000.
Beveiligingsnotities
Sectie met titel “Beveiligingsnotities”Retained-modus verbreedt het invoeroppervlak niet. Het HTML-beveiligingsbeleid, de CSS-eigenschappenallowlist en de parsercaps gelden onveranderd. Het behouden node-budget is zelf een grens tegen het uitputten van bronnen: het begrenst hoeveel structuur de engine voor één document zal vasthouden.
Conformiteit
Sectie met titel “Conformiteit”| Statement | Spec | Clause |
|---|---|---|
grid-template-areas benoemt grid-cellen; named areas plaatsen items. | W3C CSS Grid Layout Module Level 1 | §7.3 |
Expliciete vaste, percentage- en fr-tracks krijgen hun grootte tegen de contentbreedte. | W3C CSS Grid Layout Module Level 1 | §7.2 |
Dit is een previewimplementatie van een grid-template-areas-subset met definite
columns. De geverifieerde status per eigenschap wordt bijgehouden in de
CSS-ondersteuningsmatrix; hier wordt geen
end-to-end-conformiteit geclaimd. Er wordt geen standaardtekst gereproduceerd.