Repository navigation
Configuration Page and Layout
Part of the Configuration reference.
Generated from docs/configuration-page-layout-en.mdx (updated 2026-10-16). Read it on postext.dev, where it is also available in Spanish, Catalan, Portuguese, French, German, Italian, Chinese, Japanese and Arabic. To change this page, edit the MDX and run pnpm wiki in apps/web.
The page property controls the physical dimensions and appearance of the page.
| Property | Type | Default | Description |
|---|---|---|---|
sizePreset |
PageSizePreset |
'17x24' |
Predefined page size. Set to 'custom' to use explicit width/height. |
width |
Dimension |
17 cm |
Page width. Taken from sizePreset when omitted; an explicit value always wins (use sizePreset: 'custom' for fully custom sizes). |
height |
Dimension |
24 cm |
Page height. Taken from sizePreset when omitted; an explicit value always wins. |
margins |
PageMargins |
2 cm all sides |
Space between the page edge and the content area. Each side (top, bottom, left, right) is set independently. With mirror: true the margins are facing-page margins: left is the inner (spine-side) margin and right the outer one; odd pages (page 1 is odd) keep them as written and even pages swap them, so the content area — and with it the columns, float bands, header/footer containers and opener bands — moves across the spread. Default false. See below. |
backgroundColor |
ColorValue |
transparent |
Page background color. |
dpi |
number |
300 |
The pixels per inch the layout works in: how physical units (cm, mm, in, pt) become its pixels. A bitmap without a resolution of its own takes one layout pixel per image pixel, so it prints at this many ppi: keep 300 for print, or give the pictures a resolution (Resource.bitmap.resolution, layout.bitmapResolution; see Document format › Bitmap size). The preflight checks each picture's effective resolution. |
cutLines |
CutLinesConfig |
disabled | Show trim marks at page corners for print cutting. When enabled, the canvas expands to include bleed area and crop marks. See below. |
baselineGrid |
BaselineGridConfig |
disabled | Draw the baseline grid over the pages, to check the vertical rhythm. The layout snaps to the grid whether or not it is drawn. See below. |
binding |
'auto' | 'left' | 'right' |
'auto' |
The edge the book is bound on. 'auto' is 'right' when layout.writingMode is 'vertical-rl', when the document runs right to left (direction) or when its comics section reads right to left (a manga, a Japanese or Traditional Chinese edition), else 'left'. A right-bound book opens on a left page and mirrors its margins the other way round. Book-level: a heading style's own layout never changes it. See Binding. |
Books are read as spreads, and the inner margin usually differs from the outer one. margins.mirror turns the four margins into facing-page margins:
{
"page": {
"margins": {
"top": { "value": 2, "unit": "cm" },
"bottom": { "value": 2.5, "unit": "cm" },
"left": { "value": 2.2, "unit": "cm" },
"right": { "value": 1.4, "unit": "cm" },
"mirror": true
}
}
}With this configuration every odd page has a 2.2 cm margin on the left (the spine) and 1.4 cm on the right (the fore-edge); every even page has 1.4 cm on the left (the fore-edge) and 2.2 cm on the right (the spine). Each laid-out page carries its own contentArea on the VDTPage, so everything derived from it — columns, full-width float bands, header and footer containers, and span: 'page' opener bands — follows the mirrored geometry automatically. Page and bleed frames used by design elements anchored to 'page' / 'bleed' are not affected: they describe the physical sheet, not the margins.
"Vertically set Chinese documents are bound on the right-hand side, and horizontally set documents are bound on the left-hand side" (clreq §7.1.1.1). page.binding: 'right' lays a book out for the right edge:
- Page 1 is still odd and still the recto, so
breakBefore.parity,:::pagebreak{parity}, design elements with aparityand every page count keep their meaning. What changes is the side the recto sits on: the left page of the spread. A chapter that opens on a new recto opens on a left page (clreq §7.1.3.3). - With
margins.mirror,leftis still the inner margin, but it is the odd pages that swap: page 1 has its inner margin on its right, page 2 on its left. AoneAndHalfside column at'outer'/'inner', a rotated float that sits against the spine, part-page margins and box corner icons at'outer'/'inner'follow the same rule. - The document says so (
VDTDocument.binding: 'right'), so a host never has to read the config: the Sandbox shows its spreads as[3 | 2]with page 1 alone on the left of the spine, and its HTML viewer runs the pages right to left, opening at the right end, the left arrow going to the next page.renderToHtmlin multi mode lays the row out right to left. - The PDF carries
/ViewerPreferences << /Direction /R2L >>and/PageLayout /TwoPageRight(page 1 alone, then pairs), tagged or not. Acrobat and Foxit follow them; Chrome's built-in viewer ignores both.
Folios and running heads do not move by themselves: a template that prints the page number at the outer corner needs its odd and even elements set for the right edge (elements take a parity).
A book written right to left (Arabic, Persian, Hebrew…) is bound on the right as well: 'auto' gives the right edge when the document's direction resolves to 'rtl'. Such a book also mirrors its whole flow, so its first column is the right one and its indents, list markers, floats and notes stand on the right; header and footer slots stay physical. See Arabic layout.
A comic book read right to left is bound on the right too: 'auto' gives the right edge when the config has a comics section whose reading direction resolves to 'rtl'. That is the case of a manga (comics.artDirection: 'rtl') and of a Japanese or Traditional Chinese edition of a Western comic. The section decides for the whole book, not the :::page blocks of one chapter. See Comics.
| Preset | Width | Height | Common use |
|---|---|---|---|
'11x17' |
11 cm | 17 cm | Pocket books |
'12x19' |
12 cm | 19 cm | Standard paperback |
'17x24' |
17 cm | 24 cm | Technical books, textbooks |
'21x28' |
21 cm | 28 cm | Magazines, reports (near A4) |
'broadsheet' |
375 mm | 597 mm | Broadsheet newspapers |
'berliner' |
315 mm | 470 mm | Berliner newspapers |
'tabloid' |
280 mm | 430 mm | Tabloid newspapers |
'compact' |
297 mm | 420 mm | Compact newspapers (a broadsheet folded in half) |
Figure: Page size presets Four built-in page size presets drawn to proportional scale: pocket 11x17, paperback 12x19, technical 17x24, and near-A4 21x28 cm.
Presets drawn to proportional scale.
The four newspaper formats are new in postext 1.18 and are left out of the drawing: a broadsheet page has almost four times the area of a 21 × 28 one. They are usually set with the 'multiple' layout; six columns are common on a broadsheet and five on a tabloid.
The baseline grid is the rhythm of the body text: lines one body line height apart, counted from the top of the content area. The layout uses it whether or not it is drawn: headings, list ends, boxes, figures and display formulas bring the text back onto it (unless their own snapToGrid is off), so the lines of adjacent columns stay aligned. enabled only draws the lines, in the canvas, the PDF and the Sandbox views, to check that rhythm; turning it on or off moves nothing. The lines span only the page's actual text — from the first text line to the last — so float bands, blank parity pages, and unused tail space show no grid.
| Property | Type | Default | Description |
|---|---|---|---|
enabled |
boolean |
false |
Whether to draw the grid lines (canvas and PDF). Only the drawing: the layout is the same either way. |
color |
ColorValue |
#cccccc |
Color of the grid lines. |
lineWidth |
Dimension |
0.5 pt |
Thickness of the grid lines. |
page: {
baselineGrid: { enabled: true, color: { hex: '#e0e0e0', model: 'hex' } }
}When enabled, the canvas expands to include a bleed area and the engine draws crop marks at each corner for print production. The PDF gives every page a TrimBox and a BleedBox; a PDF/X file has them even without cut lines. In the Sandbox they are set in Export › Print preparation.
| Property | Type | Default | Description |
|---|---|---|---|
enabled |
boolean |
false |
Whether to expand the canvas with bleed and draw crop marks. |
bleed |
Dimension |
3 mm |
Extra area around the page used for print bleed. |
markLength |
Dimension |
5 mm |
Length of each crop mark. |
markOffset |
Dimension |
3 mm |
Gap between the trim edge and the start of each crop mark. A mark never starts inside the bleed: when bleed is wider, the mark starts at the bleed edge. |
markWidth |
Dimension |
0.25 pt |
Thickness of the crop marks. |
color |
ColorValue |
#000000 |
Color of the crop marks on the canvas (the screen preview). The PDF always paints them in registration colour (see below). |
The sheet grows by bleed + markOffset + markLength on every side, and the trimmed page sits in its middle. Each corner of the trim gets two marks, markLength long, each in line with one of the edges that meet there. A mark starts markOffset outside the trim, or at the bleed edge when bleed is the wider of the two, so no mark lies over art that runs into the bleed. With the defaults (3 mm of bleed, a 3 mm offset) the marks run from 3 to 8 mm outside the trim, and a blank band 3 mm wide runs round the sheet outside them. cropMarkSegments(page, doc.config.page, doc.trimOffset) returns the eight marks of a page in page pixels, the ones the canvas and PDF backends draw. The third argument is where the trim sits inside the sheet, the value the PDF's TrimBox is written from; left out, it is worked out from cutLines the same way.
Nothing but the marks prints outside the bleed. Everything the page paints, the design elements anchored to 'page' or 'bleed' included, is clipped to the bleed box on the canvas, in the PDF and in the HTML output, as a DTP export clips it: a band or a picture set past the bleed on purpose is cut at the bleed edge, where the trimmer would lose it anyway. Up to postext 1.4 such an element ran on over the marks to the edge of the sheet.
In the PDF (postext-pdf), the MediaBox of each page is the whole sheet. The page also carries a TrimBox, the trimmed page, and a BleedBox, the trim plus the bleed, which imposition and preflight tools read. The marks are painted in registration colour, the /All separation, so they print on every plate. This holds whatever colour space the PDF is written in (RGB, grayscale or CMYK): a plain black would reach the printer as rich black or as the black plate alone. color only applies to the canvas.
The page.pageNumbering block controls how page labels are formatted and where the counter starts. It only defines the document-wide default — to restart numbering mid-document (e.g. roman-numeral front matter switching to decimal chapters from 1), use the :::numbering directive (see Document format → Directives).
| Property | Type | Default | Description |
|---|---|---|---|
format |
'decimal' | 'lower-roman' | 'upper-roman' | 'lower-alpha' | 'upper-alpha', or an East Asian style |
'decimal' |
Numeric style used to render page labels. The East Asian styles ('trad-chinese-informal' numbers the pages 一, 二, 三) are listed under Numbering format spellings. |
startAt |
number |
1 |
Numeric value assigned to the first page regardless of format. format: 'lower-roman', startAt: 1 yields i, ii, iii, …; format: 'decimal', startAt: 17 yields 17, 18, 19, …. |
The computed label is stored on every VDTPage as pageLabel and is what the {pageNumber} header/footer placeholder resolves to. PDFs emit a /PageLabels number tree so Preview / Acrobat's page indicator and "Go to page" navigation match the printed labels exactly. A style PDF has no code for (Chinese numerals, circled and fullwidth digits) is written out page by page, so the reader shows 一, 二, 三 too.
Three settings choose a numbering format, and each grew its own spelling: page labels (page.pageNumbering.format and :::numbering{format=…}) say lower-roman, ordered lists (orderedLists.numberFormat) say arabic for decimal, and resource types (counterFormat) say roman-lower. Every one of them accepts all the spellings below, so a format copied from one setting works in the others. Names are case-insensitive; the one-character forms are not (i and I differ).
| Format | Prints | Accepted spellings |
|---|---|---|
| Decimal | 1, 2, 3 |
decimal, arabic, 1
|
| Lower roman | i, ii, iii |
lower-roman, roman-lower, i
|
| Upper roman | I, II, III |
upper-roman, roman-upper, I
|
| Lower alpha | a, b, c |
lower-alpha, alpha-lower, lower-latin, a
|
| Upper alpha | A, B, C |
upper-alpha, alpha-upper, upper-latin, A
|
| Chinese numerals, Simplified | 一, 十二, 一百零一 |
simp-chinese-informal, 一 in a Simplified document |
| Chinese numerals, Traditional | 一, 十二, 一萬 |
trad-chinese-informal, cjk-ideographic, 一 in a Traditional document |
| Chinese financial numerals, Simplified | 壹, 壹拾贰, 壹佰贰拾 |
simp-chinese-formal, 壹 in a Simplified document |
| Chinese financial numerals, Traditional | 壹, 壹拾貳, 壹佰貳拾 |
trad-chinese-formal, 壹 in a Traditional document |
| Chinese digits | 一二〇, 二〇二六 |
cjk-decimal, 〇
|
| Heavenly stems | 甲, 乙, 丙 … 癸 |
cjk-heavenly-stem, 甲
|
| Earthly branches | 子, 丑, 寅 … 亥 |
cjk-earthly-branch, 子
|
| Japanese numerals | 一, 十二, 百一, 一万一 |
japanese-informal, 一 in a Japanese document |
| Japanese formal numerals | 壱, 壱拾弐, 壱百 |
japanese-formal, 壱
|
| Hiragana, gojūon order | あ, い, う … ん, ああ |
hiragana, あ
|
| Katakana, gojūon order | ア, イ, ウ … ン, アア |
katakana, ア
|
| Hiragana, iroha order | い, ろ, は … す, いい |
hiragana-iroha, い
|
| Katakana, iroha order | イ, ロ, ハ … ス, イイ |
katakana-iroha, イ
|
| Circled | ①, ②, ③ … ㊿ |
circled-decimal, ①
|
| Fullwidth digits | 1, 2, 3 |
fullwidth-decimal, 1
|
| Arabic-Indic digits | ١, ٢, ٣ … ١٠ |
arabic-indic, ١
|
| Persian digits | ۱, ۲, ۳ … ۱۰ |
persian, urdu, ۱
|
| Arabic letters, abjad order | أ, ب, ج, د, هـ … غ, أأ |
abjad, أبجد
|
| Arabic letters, alphabetical order | أ, ب, ت, ث … ي, أأ |
hijai, arabic-alpha, arabic-alphabetic, أبتث
|
| Abjad numerals | ا, ب … يا (11), غتمو (1446) | arabic-abjad |
| Abjad numerals, Maghrebi values | ص (60), ض (90), ش (1000) |
arabic-abjad-maghrebi, maghrebi-abjad
|
The East Asian styles keep their CSS Counter Styles names in all three settings. The informal Chinese numerals write 十 for 10 to 19 without a leading 一 (十二, but 一百一十), one 零 for a run of zeros inside the number (一百零一, 一千零五十), and 万 or 萬 for ten thousand, 亿 or 億 for a hundred million (一万零一十). Only cjk-decimal uses 〇, digit by digit, the way years are written (二〇二六, GB/T 15835—2011). The stems stop at 10, the branches at 12 and the circled digits at 50; past them the number prints in digits. 一 and 壹 follow the script of the document's locale: Traditional for zh-Hant, zh-TW or zh-HK, Simplified otherwise. Some older editions write 101 as 一百一 with no 零; Postext does not print that form.
The Japanese styles (since postext 1.16) follow CSS Counter Styles too. japanese-informal writes 十 without a leading 一 and no 零 for an empty place (百一, 千十), and japanese-formal the 大字 壱 弐 参 拾 百 阡 with 壱 kept before each unit (壱拾, 壱百). CSS stops both at 9 999; Postext goes on in groups of four digits with 万 億 兆 (formal 萬 億 兆), each group keeping its 一 before a unit: 一万一 is 10 001, 一億一万 100 010 000. In a Japanese document (ja, ja-JP…) 一 means japanese-informal, so 第{1:一}章 prints 第百一章 there and 第一百零一章 in a Chinese one; 壹 stays the Chinese formal numerals. The kana series are the CSS lists: 48 kana in gojūon order (ゐ and ゑ included) and 47 in the order of the iroha poem; past the last they go on with two kana (ああ, いい), and they have no zero, so an item numbered 0 prints 0. Positional kanji digits (二〇二六), the form of years and folios, are cjk-decimal.
The Arabic styles keep the CSS names where CSS has one (arabic-indic, persian; urdu and maghrebi-abjad from the W3C Ready-made Counter Styles are read as persian and arabic-abjad-maghrebi). arabic keeps its old meaning, the European digits. arabic-abjad writes the additive abjad numerals of Classical Arabic and manuscript foliation, highest value first: 11 is يا, 1446 غتمو, and the thousands count goes before غ (2000 بغ, 1002 غب); past 999 999 the number prints in digits. The W3C note uses the name for a 28-letter series where 11 is ك; Postext calls that series abjad, the lettering of list items in abjad order (أ، ب، ج، د، هـ), and hijai the alphabetical order (أ، ب، ت، ث). Both write the first letter with its hamza (أ), and a heh that would stand alone as هـ, with a tatweel, so neither is read as the digits ١ and ٥; past 28 they double, as lower-alpha does (أأ, أب). The Maghrebi values follow the mnemonic صعفض قرست ثخذ ظغش (ص 60, ض 90); the W3C list swaps ص and ض. A single أ cannot tell the two letter series apart, so their tokens are their first four letters: {1:أبجد}, {1:أبتث}. A document's own digits are set with numerals.
The other spellings are for configurations that nothing type-checks: JSON presets and plain JavaScript. The TypeScript types still name only each setting's own spelling — the one the Sandbox writes and resolveAllConfig returns, the East Asian names included — so a typed PostextConfig keeps to it, and another spelling needs a cast.
// JavaScript or a JSON preset (in TypeScript, each setting's own spelling)
orderedLists: { numberFormat: 'decimal' }, // same as 'arabic'
page: { pageNumbering: { format: 'roman-lower' } }, // same as 'lower-roman'
resourceTypes: [{ id: 'plate', counterFormat: 'upper-roman', … }], // same as 'roman-upper'resolveAllConfig turns the list and page formats into their own setting's spelling — 'decimal' resolves to 'arabic' in orderedLists, 'roman-lower' to 'lower-roman' in page.pageNumbering — and stripConfigDefaults drops a spelling of the default. The Sandbox panels show each of the three settings in its own spelling, whichever one the configuration uses. Any other value — roman, 01, a typo — numbers in decimal instead of printing undefined, and is reported as a configuration warning. The heading numbering templates take the same names after the colon ({1:roman-upper} is {1:I}), next to their own zero-padded {1:01}.
The layout property controls how columns are arranged within the content area.
Figure: Columns, gutter, and margin A page divided into three columns: each column is the content area for text, gutters are the vertical gaps between columns, and the margin is the blank edge between the page boundary and the first column.
Columns hold text. Gutters separate them. Margins frame the content.
Figure: Margin system A page with independent top, right, bottom, and left margins surrounding the content area.
Each side of the page can have its own margin.
| Property | Type | Default | Description |
|---|---|---|---|
layoutType |
'single' | 'double' | 'oneAndHalf' | 'multiple' |
'double' |
Column arrangement. See below for details on each type. |
columnCount |
number |
3 |
How many equal columns a 'multiple' layout cuts the body into: a whole number from 3 to 8. A value outside that range, or not a whole number, is clamped and reported (see Layout types). A heading style's own 'multiple' layout takes the document's count unless it sets its own. Since postext 1.18. |
gutterWidth |
Dimension |
0.75 cm |
Horizontal space between columns. Only applies to multi-column layouts. |
sideColumnPercent |
number |
33 |
Width of the side column as a percentage of the content area. Any value that leaves both columns some width is used as written; one that would not is clamped, and the build reports it (see Layout types). Only applies to 'oneAndHalf' layout. |
sideColumnRole |
'text' | 'floats' |
'text' |
What the side column carries: body text (it flows there after the main column), or only the resources and callouts placed with span: 'side' — a float-only margin column. 'oneAndHalf' only. With 'text', a paragraph that runs on from one column into the other is broken again for the width of the column it goes on in; up to postext 1.4 it kept the lines of the column it started in, and a line set for the main column ran past the side one, which clipped it. |
sideColumnSide |
'right' | 'left' | 'outer' | 'inner' |
'right' |
Edge of the content area the side column sits at. 'outer' / 'inner' follow the page parity when the margins are mirrored (a recto's outer edge is its right edge, a verso's its left). 'oneAndHalf' only. |
columnRule |
ColumnRuleConfig |
disabled | Optional visual rule drawn between columns. See below. |
fitFiguresToPage |
boolean |
false |
Shrink a figure (bitmap or SVG) whose image, caption and note would stand taller than the content area until they fit it (a picture with a safe area, Resource.safeArea, is first cropped within it at its full width, and only shrunk if it still does not fit), and set an inline figure a little too tall for the room left in its column smaller (down to half its width, the caption keeping the column's measure) so it stays with its text. A shrunk image sits in its slot per placement.align. The HTML viewer turns it on, since its pages are only as tall as the screen; printed pages are sized for their figures. |
bitmapResolution |
'document' | 'file' | number |
'document' |
How a bitmap without its own bitmap.resolution takes its natural print size. 'document' reads its pixels at page.dpi; a number is the ppi of every such bitmap (300: a 2400 px picture is 203.2 mm wide whatever the page's dpi); 'file' uses the resolution its file states (bitmap.fileResolution), 72 and 96 counting as unset, else page.dpi. The column still caps the picture, and a smaller one is never enlarged. See Document format › Bitmap size. Since postext 1.24. |
floatShrink |
FloatShrinkConfig |
mode: 'never' |
The document default for a floated picture's placement.shrink (mode: 'never', 'page' or 'slot') and placement.minScale (minScale, 0.7 when unset): scale the picture down, keeping its proportions, to the room of its slot instead of moving it on (see Document format › Placement). A resource's placement, then its type's defaultPlacement, override it. fitFiguresToPage caps every figure at the content area; floatShrink looks at the band a float would really take, under an opener, beside other floats or over footnotes. Since postext 1.24. |
wrap |
TextWrapConfig |
minTextWidth: 12em, minLinesBeside: 2, defaultWidth: 0.45
|
Text running beside a picture or a box narrower than its column (placement.wrap, a box's wrap): gap, the space between the item and the text (one body line when unset); minTextWidth, the narrowest measure the text beside it may take, a length or a share of the column (narrower: the item takes its band whole, with a textWrap warning); minLinesBeside, the fewest lines worth setting beside it; defaultWidth, the share of the column a wrapped item takes when it sets no width. See Document format › Text wrap. Since postext 1.24. |
floatsAtCitingPage |
boolean |
false |
The document default for placement.citingPage: a 'top' or 'auto' float may take the head of the page (a page-span float) or of the column (a column float) where the line that first cites it lands, instead of the first free slot after that line; the text above the reference moves down under it (see Document format › Placement). A resource's placement, then its type's defaultPlacement, override it. Since postext 1.25. |
maxTopFraction |
number |
0.7 |
The largest share of a column's height, 0 to 1, that a float heading the page or column that cites it may take, with the floats already standing there, so the page keeps room for its text (LaTeX's \topfraction). A float that would take more goes to its usual slot. Since postext 1.25. |
hugClosingFloats |
boolean |
true |
On the closing page of a chapter (and of the document), the page-wide figures and tables set below the last band of text move up to sit one float gap under it, stacked in their order: nothing follows them there. false leaves them where their placement put them, so a position: 'bottom' float ends at the page foot on the closing page as on every other page — a datasheet whose outline ends at the same height on every page, say. Pages with a side column never move them. |
inlineResourceGap |
'around' | 'above' |
'around' |
Where an inline resource (placement.position: 'here', embedded with ::resource) keeps the float gap, a line. 'around' keeps it above and below the resource, and the text after it goes back onto the baseline grid under that gap; a heading, a list, a box or another inline resource right after it shares the gap below with its own space above, the larger of the two applying. 'above' keeps it above only: the text after the resource resumes at the next grid line, however close that is — anywhere from nothing to a line — as up to postext 1.4. Configurations stored by earlier versions whose chapters embed a resource are read with 'above', so their pages do not move (see Bundles written by postext 1.4 or earlier). A configuration written in code for 1.4 keeps the old spacing by setting 'above' itself, or through pinLegacyInlineGap from postext/bundle. |
inlineResourceGapInBoxes |
boolean |
true |
Whether an inline resource inside a box (:::callout) keeps the gap inlineResourceGap sets, a line of the box's own text: above the resource, and below it too with 'around', the larger of it and the next block's own space applying. At the top or the foot of the box, or of a fragment of a split box, the padding sets the resource off instead and no gap is added. false sets the resource right under the text before it and the text after it right under the resource, as up to postext 1.4. Configurations stored by earlier versions whose chapters embed a resource inside a box are read with false (see Bundles written by postext 1.4 or earlier); in code, pinLegacyBoxResourceGap from postext/bundle does the same. |
inlineCaptionSide |
boolean |
true |
Whether a resource set in the text (position: 'here') takes placement.captionSide as a column float does. In a column-and-a-half layout whose side column is kept for floats (sideColumnRole: 'floats') its caption and note go to the side column, level with the top of its body, where that column is free beside it; the block in the text column is then as tall as the body alone. Where the side column is taken, and on a page without one, the caption stays under the body. false keeps side captions to column floats, as up to postext 1.27. Since postext 1.28. Configurations stored by earlier versions with a 'oneAndHalf' layout whose chapters embed a resource are read with false; in code, pinLegacyInlineCaptionSide from postext/bundle does the same. |
boxChildSplitMinLines |
number |
2 |
Fewest lines of a paragraph or list item that a cut inside it leaves on each side when a box splits (splitMinLines, under Callout styles, still counts every line of the box on each side of the cut). A whole number, at least 1. With the default a cut never leaves a lone line of a paragraph or item at the foot of a column or at the head of the next; a box style whose splitMinLines is lower sets the limit instead. 1 lets a cut leave one line of the paragraph or item on a side, as up to postext 1.4. Configurations stored by earlier versions whose chapters hold a :::callout are read with 1 (see Bundles written by postext 1.4 or earlier); in code, pinLegacyBoxChildCut from postext/bundle does the same. |
flowColumns |
boolean |
true |
A :::columns fence outside a box sets its blocks in sub-columns of the text column (or across the page with span="page"), and a group, in a box or in the text, is cut between its sub-columns when it does not fit, going on in the next column or page (see Document format › :::columns). false ignores the fence outside a box and never cuts inside a group, as up to postext 1.24; configurations stored by earlier versions whose chapters hold a :::columns fence are read with false; in code, pinLegacyFlowColumns from postext/bundle does the same. A styled section keeps the document's value. Since postext 1.25. |
floatsUnderOpener |
boolean |
true |
Under a page-wide opener (a heading level or style with span: 'page') set over two or more text columns, the head of the opener's own column, right under its band, is a slot for a 'top' or 'auto' float, level with the heads of the other columns: a floated box fenced right after the opener, or a resource embedded there, sits under the opener in the first column (across several columns from it with columns), and the column's text starts under it. A float cited in running text still follows the line that cites it. false offers no slot there, so such a float lands from the second column on, as up to postext 1.24; configurations stored by earlier versions that set a page-wide heading are read with false; in code, pinLegacyOpenerHeadFloats from postext/bundle does the same. A styled section keeps the document's value. Since postext 1.25. |
openerFloats |
'allow' | 'warn' | 'avoid' |
'allow' |
Floats on an opener page: the page a part opens, the page a heading opens with its own break (breakBefore, or a span: 'page' heading that opens a page), and the first page of a document that starts with a heading. A float is a figure, a table or a comic strip with a floating placement, or a :::callout floated to the head or foot of a page, whether it takes a column, the page width or the side column; a resource embedded inline ('here'), a 'fixed' box and a span: 'side' box are not. 'allow' sets floats there as on any page. 'warn' lays the page out the same and reports each float on it (an openerFloat warning, see Warnings in the document). 'avoid' keeps the opener page clear: a float that would land there takes the first free slot after it, so the page holds its opener and text alone. A styled section keeps the document's value. Since postext 1.28. |
writingMode |
'horizontal-tb' | 'vertical-rl' |
'horizontal-tb' |
How lines run. 'vertical-rl' sets Chinese and Japanese text vertically: characters top to bottom, each line to the left of the one before. A heading style's layout inherits it unless it sets its own, so a horizontal appendix can follow a vertical book. See Vertical writing. |
With writingMode: 'vertical-rl' a page is laid out as a horizontal page turned a quarter turn clockwise. The flow is set in a frame as wide as the sheet is tall; its lines are the columns of vertical text, read from the right, and everything the engine does with lines (breaking, justification, floats, footnotes, keep-together rules) works in that frame. So, on the sheet:
- A column of the layout is a tier (栏):
layoutType: 'double'gives two tiers stacked top to bottom, filled from the upper right;gutterWidthis the gap between them and the column rule a horizontal rule between them. Tiers are not balanced at the end of a chapter (clreq §7.1.3.4): column balancing is off in a vertical document unlessheadings.balancing.enabledis set. - What the flow calls "top" is the sheet's right edge, where reading starts: a top float sits at the right of the page, a bottom float at the left, a page-span opener is a band down the right edge, footnotes land at the left end of each tier. A design element anchored to the top of the page (a heading design, a fixed box) is anchored to the right edge.
sideColumnSide'left'is the top tier,'right'the bottom one;'outer'and'inner'read as'right'and'left'. - The flow's margins are the sheet's margins turned: the right margin is the top of the flow, the top margin its left.
page.marginskeep their names on the sheet. - Running heads, folios, crop marks and the page background stay on the sheet, set horizontally, as clreq describes for vertical books.
-
Figures and tables stand upright. A figure fills the height of its tier as far as its caption allows, at most as wide as the page; the width it takes is the room it uses in the flow. Its caption is set horizontally under it, and so are the cells of a table: both are measured as horizontal text. A table is set upright across the page, its rows cut to the tier when it is taller.
placement.alignsets a figure at the top ('left'), middle or foot of its tier. Aplacement.rotateis not applied where the figure is first referred to in vertical text: the build reports arotateIgnoredVerticalcontent warning. A horizontal section of the book (a heading style whoselayoutsets'horizontal-tb') turns its figures as asked. - A picture of a design (an opener's illustration, a part page's) stands upright too. Its box in the flow is sized with the picture's width and height swapped, so
size.widthis how far the picture runs down the column and its width on the sheet follows from its proportions. - Characters: Han, kana and fullwidth forms stand upright, one em each; Latin words and numbers are turned sideways with their horizontal widths; punctuation takes the font's vertical form. Pause and stop marks are never turned: a mainland font sets 、。,. in the top-right corner of the cell and !?:; in its right half, a Taiwan or Hong Kong font centres them (
cjk.region). Brackets take their vertical forms, and “ ” ‘ ’ in mainland text read as 『』「」. Dashes, ellipses and the wave dash take the font's vertical form where it has one (Noto CJK keys that of — toverttogether withfwid: a rule down the middle of the cell), else they are turned with their ink centred on the column's axis. A 破折号 (——) in Chinese text is one rule down the column: its vertical forms would leave blank at both ends of each cell, so each dash is turned with the line and stretched as in horizontal text (see Punctuation widths). A number of at most two digits stands in one upright cell, unless it sits in a Latin sentence, whose words it follows (see Numbers in vertical text). The interpunct (·) takes half a cell in mainland text and a whole cell in Taiwan and Hong Kong text. The signs Unicode sets upright (× © ± § ℃ ① and the like) stand in a cell of their own, inside a number too:3×4is 3 and 4 sideways with × upright between them. An apostrophe or an interpunct between two letters of a Latin word (don’t,l·l) stays in the word, sideways. A Latin paragraph in a vertical flow follows the same rules. Inline formulas, chips and swatches are turned sideways with the line. - Every character is measured as it is painted: a cell advances its cell down the line, a sideways run its horizontal width. Text that stays horizontal on the sheet (running heads, folios, captions, table cells) is measured horizontally.
- The punctuation widths, hanging punctuation and the space between Han and Latin apply down the line as they apply across it. The blank before a glyph is above it and the blank after it below: a Kaiming 、 takes half a cell,
」「compress to a cell and a half, an opening bracket trimmed at the head of a line starts half a cell higher, a hung 。 sits under the foot of its line, and the Han–Latin space is a quarter em of the column above and below a sideways word.:;?!keep a whole cell in vertical text in every region. - The character grid counts characters down the line and lines across the page:
charsPerLinesets how long a tier is,linesPerPagehow many lines a page holds, andlayoutType: 'double'gives two tiers of whole characters with a gutter of whole ems between them.
For hosts reading the layout: a vertical page carries VDTPage.flow. Its contentArea, columns, blocks, lines, floats, footnote areas, opener band and block design overlays are in flow coordinates; width, height, header and footer are on the sheet. flowToPage, pageToFlow, flowRectToPage and pageRectToFlow map between the two, and verticalOrientation(char, region) says how a character stands. flow.centralBaselines gives, per font family, the axis the layout centred upright characters on: the centre of the ink of 中, whose long stroke runs the height of the em box (0.38 em above the baseline in Noto Serif and Noto Sans, SC and TC alike), and which every Chinese, Japanese and Korean face has. Each line is centred on that axis: a vertical line's baseline sits half its line height plus the family's central baseline below the top of its line box (a horizontal line's sits 0.8 of its line height down), so a column of characters stands in the middle of its pitch and a rule drawn between two columns at a whole pitch falls halfway between them. A vertical design text is set the same way in its own lines. The canvas paints a vertical page itself; to paint punctuation with the font's own vertical forms a browser host loads, once per family, a twin face with them switched on: loadVerticalAlternates(family, faces), where faces are the family's sources (URLs or bytes) and descriptors. The twin is kept only where the browser applies the feature to canvas text (Chrome 140 and later): it draws 「(《 with the twin and with a copy of the same faces loaded without the feature, at the weight and style of the faces given, and keeps the twin when their ink differs. A later call for other faces of a family whose twin is in use (the bold after the regular) adds them to it. The Sandbox does this for every family of a vertical document. Without a twin, brackets are turned about their em box and mainland pause and stop marks moved within their cell where the font's vertical forms put them: 、。,. to the top-right corner (within 0.07 em of Noto Serif SC's vertical forms), !?:; half an em to the right and a little up (within 0.02 em). The PDF and the HTML set the same page: see Vertical text in the PDF and the table under How the HTML output differs from canvas and PDF. Checked cell by cell against HarfBuzz (vertical layout with vert) in Noto Serif TC and SC, every character of 「賈雨村」云云,宜乎?故曰!;:、。“引”‘單’…… stands within 0.02 em of it on the canvas and in the PDF, and within 0.05 em in the HTML (Chrome centres a turned glyph on the middle of the font's ascent and descent, which in Noto is 0.05 em above its em box's centre). flow.dashAdvances gives, per family, the horizontal advance in ems of each dash the page stretches to fill its cell (— – ― ⸺ ⸻ -), for a renderer with no font metrics of its own: the HTML stretches the dash by it, as the canvas and the PDF do from theirs. Running heads and folios can be set vertically too: see Vertical text elements.
Draws a thin vertical line in the gutter to visually separate columns.
| Property | Type | Default | Description |
|---|---|---|---|
enabled |
boolean |
false |
Whether to draw the column rule. |
color |
ColorValue |
#cccccc |
Color of the rule line. |
lineWidth |
Dimension |
0.5 pt |
Thickness of the rule line. |
Under a page-span heading (span: 'page') the rule starts where the text of the columns starts, under the heading's band, whether the default opener or a design of its own paints the band. Up to postext 1.4 it ran from the top of the text block, through the band.
A heading style can set a rule of its own in its layout (see Heading styles), and the pages of its section draw that one. A field the style leaves unset takes the document's value, so a section that only changes its columns keeps the document's rule. Up to postext 1.4 a style's rule was never drawn: every page drew the document's.
-
'single'— One column spanning the full content width. Best for narrow pages or text-heavy content with long paragraphs. -
'double'— Two equal-width columns. The classic editorial layout — keeps line measure within the optimal 40–50 character range for comfortable reading. -
'oneAndHalf'— An asymmetric layout with a main column and a narrower side column. The side column (controlled bysideColumnPercent) is ideal for margin notes, small figures, or supporting content. Values between 25–40% work well, and a narrow channel for line numbers or marginal marks takes around 10–15%. The side column issideColumnPercent% of the content width and the main column is what is left after the gutter — so at 50% the side column is one gutter wider than the main one. Any value is laid out as written while both columns keep at least 1% of the content width; one that would leave either narrower — 0 or below, or one so wide that the main column vanishes behind the gutter — is clamped to the nearest value that keeps both, and a value that is not a number takes the default, 33. The document'sconfigWarningsthen carry{ kind: 'sideColumnPercentClamped', path: 'layout.sideColumnPercent', value, used }— the path of a heading style's ownlayoutnames the style, as inheadingStyles[2].layout.sideColumnPercent, and is measured on that style's margins — which the Sandbox lists in its Checks panel;collectConfigWarnings(config)returns the same list without laying anything out. A layout that is not'oneAndHalf'never reads the value, and never reports it. WithsideColumnRole: 'floats'the body text never enters the side column: it becomes a channel for the figures, tables and callouts placed withspan: 'side'. A side figure or table stacks from the head of the channel on the page that first cites it — the marginal figure of a textbook sits at the top of its page even when the text cites it further down; one that cannot fit the rest of the channel waits for the next page's. A side box stacks beside the text it interrupts, and when the rest of the channel cannot hold it there it slides up to the lowest position that still fits (its foot on the channel's foot), or waits for the next page. When the text after a box's fence continues on the next page (the column is full, or the break rules move that text on), the box stays at its fence, beside the text before it; a style withsideAtColumnEnd: 'after'sets it level with the first line of the text after the fence instead, in the next page's channel, as line numbers and marginal headings written before their line need. An element of a heading design that stands in the channel — a chapter numeral anchored in the outer margin — is kept clear of the stack too (see Reserved height).span: 'page'floats and boxes still cross both columns, and a column float withplacement.captionSideputs its caption in the channel, level with the figure. Combined with mirrored margins andsideColumnSide: 'outer', the channel sits at the outer edge of every page — the marginal column of a textbook. From postext 1.28 a figure or table set in the text (position: 'here') withcaptionSidesets its caption in the channel too (inlineCaptionSide). -
'multiple'— Three to eight equal columns, as many ascolumnCountsays (default 3): the grid of newspapers and of many magazines (since postext 1.18). Each column is(content width − (n − 1) × gutterWidth) / nwide. The text runs on from one column to the next as in a two-column layout; the column rule is drawn in every gutter, column balancing levels all the columns on a chapter's closing page and before a page-wide box, footnotes work in every column, and page-wide figures, boxes and headings cross the whole page. A figure or a floated box can take only some of the columns:placement.columns(see Resource types) and a callout style'scolumns. AcolumnCountoutside 3–8, or not a whole number, is rounded and clamped to the nearest count that is (a value that is not a number takes 3), and the document'sconfigWarningscarry{ kind: 'columnCountClamped', path: 'layout.columnCount', value, used }(the path of a heading style's ownlayoutnames the style, as inheadingStyles[1].layout.columnCount). A layout of another type never reads the value. A heading style whoselayoutis'multiple'takes the document'scolumnCountunless it sets its own, so a newspaper set in five columns can run its opinion pages in four.
Postext is MIT-licensed. Maintained by Ignacio Ferro and community contributors. See the live documentation for the most up-to-date reference.
Overview
Writing
- Document Format
- Hyphenation and Justification
- Chinese Layout
- Arabic Layout
- Japanese Layout
- Comics
- Composed Pages
- Sandbox
- Agent Skill
- Command Line
- WebMCP
Configuration
- Overview and index
- Page and layout
- Headers and footers
- Body text
- Hyphenation and language
- Headings
- Widows, orphans and balancing
- Lists and maths
- Notes and references
- East Asian typography
- Resources
- Styles and parts
- Callout boxes
- Comics
- Composed pages
- Fonts, colours, viewers
Code
Internals
External