Layout
A page design with dimensions, wrapper markup, and Flows that paginate its content.
A Layout is a page design that holds its content directly. Each Layout in a Document produces its own run of pages, in document order, so a fresh Layout starts a new page: a hard barrier across all of its flows.
Its scaffolding (headers, footers, frames) repeats on every page; its Flows are the regions whose content paginates.
A Flow is optional. A Layout with no Flow is a single fixed page: Format wraps its content in one implicit flow, lays it out once, and never paginates it, so it suits covers, posters, and hand-placed designs. Counters, references, and footnotes in that content still resolve, and a Stream or PageBreak written there behaves as if it sat inside a Flow, with the PageBreak starting a new page where you place it. Wrap a region in a Flow to paginate it.
Fields
| Name | Type | Description |
|---|---|---|
idRequired | string | Design label, mirrored to each page host as data-layout-id for CSS. Taken from data-id, or generated from the Layout's document position. Not required to be unique: several Layouts may share one label to reuse a design, so :host([data-layout-id='page']) styles every page they produce. |
widthRequired | string | Page width as a CSS pixel length (e.g. "793.71px"). |
heightRequired | string | Page height as a CSS pixel length (e.g. "1122.52px"). |
paginationStrategy | PaginationStrategy | Default pagination strategy applied to every Flow that doesn't supply its own. |
splitGranularity | SplitGranularity | Default split granularity for every Flow that doesn't supply its own or inherit one from an enclosing Flow. |
Example
An A4 layout with a header, a body Frame containing a Flow, and a footer that renders the page number with the SDK's <PageNumber /> component. The Flow holds a <table> whose rows stream in at a Stream.
export const doc = () => (
<Document title='Invoice #1234'>
<Layout id='invoice' width={793.71} height={1122.52} paginationStrategy='auto'>
<header>Invoice</header>
<main data-type='frame' data-id='body'>
<Flow>
<table>
<thead>
<tr>
<th>Item</th>
<th>Qty</th>
</tr>
</thead>
<tbody>
<Stream>
<tr>
<td>Design work</td>
<td>1</td>
</tr>
</Stream>
</tbody>
</table>
</Flow>
</main>
<footer>
Page <PageNumber />
</footer>
</Layout>
</Document>
)<template>
<Document title="Invoice #1234">
<Layout id="invoice" :width="793.71" :height="1122.52" pagination-strategy="auto">
<header>Invoice</header>
<main data-type="frame" data-id="body">
<Flow>
<table>
<thead>
<tr>
<th>Item</th>
<th>Qty</th>
</tr>
</thead>
<tbody>
<Stream>
<tr>
<td>Design work</td>
<td>1</td>
</tr>
</Stream>
</tbody>
</table>
</Flow>
</main>
<footer>
Page <PageNumber />
</footer>
</Layout>
</Document>
</template><template data-type="document" data-title="Invoice #1234">
<template
data-type="layout"
data-id="invoice"
data-width="793.71px"
data-height="1122.52px"
data-pagination-strategy="auto">
<header>Invoice</header>
<main data-type="frame" data-id="body">
<template data-type="flow">
<table>
<thead>
<tr>
<th>Item</th>
<th>Qty</th>
</tr>
</thead>
<tbody>
<template data-type="stream">
<tr>
<td>Design work</td>
<td>1</td>
</tr>
</template>
</tbody>
</table>
</template>
</main>
<footer>Page <span data-type="page-number"></span></footer>
</template>
</template>The header, footer, and <table> markup are preserved on every page rendered from this layout. Only the <tbody> rows inside the Stream paginate.
Usage
Use a Layout for a self-contained run of pages with one page design: an invoice, a report, or a cover sheet. The Layout sets the page dimensions and the wrapper markup; its Flows hold the content that paginates. Each Layout produces its own run of pages and starts a hard page barrier, so a Document with two Layouts renders two back-to-back runs.
Put content that breaks across pages inside a Flow. Markup that should reprint on every page, such as a header or footer, stays in the Layout outside any Flow.
A Flow is optional. A Layout with no Flow is a single fixed page: Format wraps its content in one implicit flow, lays it out once, and never paginates it, which suits covers, posters, and hand-placed designs where you control the page yourself. Numbering, cross-references, and footnotes still work in that content, and a <PageBreak /> you add starts a new page where you place it. Add an explicit Flow only when you want a region to paginate.
Picking a page size
The width and height fields are CSS px values. A4 at 96 dpi is 793.71 × 1122.52. For Letter, Legal, A3, and other paper sizes (including the conversion table from inches and millimeters), see Page sizes and dimensions.
Splitting one Layout into two
Two signals that you've outgrown a single Layout:
- Different page dimensions or orientation. A portrait invoice followed by a landscape data table can't share a Layout.
- Different surrounding markup. If the header, footer, or watermark differs between sets of pages, that's two Layouts. Don't try to conditionally hide pieces of one Layout. Split.
Sharing fonts, styles, or shared <style> blocks across Layouts is fine. The split is about page-level design, not styling.
When two Layouts should look identical, give them the same id. Format mirrors that id onto every page each Layout produces as data-layout-id, so a single :host([data-layout-id="report"]) rule styles all of them at once.
Constraints
- The
idis an optional CSS label, not a unique key. Setdata-idto name the Layout, or Format generates one from the Layout's document position. Several Layouts may share oneidto reuse a design. Format mirrors theidonto each page the Layout produces asdata-layout-id, so:host([data-layout-id="invoice"])in the Layout's<style>targets every page that Layout renders. - At least one Flow is required. A Layout with no Flow renders its wrapper markup but paginates nothing.
- The
widthandheightmust parse as a CSS pixel length (e.g."793.71px"). Other units are rejected.