Skip to content

03 β€” Layout and Structure (`PRINT-LAYOUT`)

Status: NORMATIVE (internal print-safe guardrail + reference) Scope: PRINT-LAYOUT-001 … PRINT-LAYOUT-013 Related: Issue #2852 Β· sections 01 Typography, 02 Color/contrast, 04 Forms, 08 Digital-to-print fidelity

Framing. Accessibility semantics (tags, reading order, roles, alt text) live in a non-printing layer. The instant a document is printed, that layer is gone. Every structural affordance a screen reader would have consumed from the tag tree must be independently re-encoded in the visual layer β€” by size, weight, spacing, position, and repetition β€” or it is simply absent for the reader holding paper. This section governs that visual re-encoding of structure.

Sourcing honesty. Nearly everything in this section is consensus practice drawn from clear-print / accessible-document guidance (e.g. APH, CNIB/Clear Print, AFB, W3C low-vision task-force notes) and typographic ergonomics β€” not codified law. MUST appears only where the rule inherits from a WCAG success criterion or the effective-communication duty (see 00 PRINT-LEGAL). Ergonomic floors are SHOULD.


Level: SHOULD Applies to: all documents Source: Clear-print consensus (CNIB Clear Print; APH guidance); reading-order ergonomics Source strength: consensus standard Machine-checkable: partial Validation: Detect column count from the page’s text-block geometry (gutters between vertically-aligned text runs). For each multi-column page, confirm columns are separated by a visible gutter β‰₯ 12 pt and that no single sentence’s baseline row spans two columns. Human confirms the intended order matches the visual left-to-right / top-to-bottom flow.

Documents SHOULD default to a single column; where multiple columns are used, each column SHOULD be separated by a gutter of at least 12 pt, columns SHOULD be balanced or clearly sequential, and no reading path SHOULD require the eye to jump between columns mid-thought. Narrow multi-column layouts that force a short measure onto low-vision readers SHOULD be avoided.

Rationale: A low-vision reader magnifying part of a page, or anyone tracking line-to-line, loses the thread when columns are ambiguous β€” the eye returns to the wrong column or reads across the gutter. On paper there is no tag-tree reading order to fall back on; the visual order is the only order. Implementation notes: Preserve-mode (β€œflyer”) PDF: never re-flow multi-column source into a false single order; keep the visual columns intact and verify the tagged reading order matches the visual columns (this is the same divergence risk PRINT-FORM-018 covers for forms). Reflow/WeasyPrint path: prefer single column for body content; if the design demands columns, set an explicit column-gap β‰₯ 12pt and never let a heading or table straddle columns. Audit/ACR: flag pages where tagged reading order crosses a detected gutter boundary in an unexpected sequence.


Level: SHOULD Applies to: all documents Source: Clear-print consensus; typographic hierarchy practice; WCAG 1.3.1 intent (structure conveyed visually) Source strength: consensus standard Machine-checkable: partial Validation: Extract per-run font size and weight; confirm each heading level is visually distinguished from body by at least one of: β‰₯ 2 pt larger size, a heavier weight, or a distinct position/space-before. Confirm the size ordering is monotonic with the semantic level (an H1 is never smaller than the H2 beneath it). Human confirms levels are consistently applied.

Heading levels SHOULD be visually distinguishable from body text and from each other using size, weight, spacing, and position β€” not tags alone. Each level SHOULD be at least 2 pt larger than or clearly heavier than the level below it, and the same visual treatment SHOULD be used for every heading of the same level throughout the document.

Rationale: In a tagged PDF a screen-reader user navigates by heading level; on paper the only β€œheading” is what looks like one. If H2 and H3 render identically, a sighted reader β€” especially one with a cognitive or low-vision disability who relies on strong visual chunking β€” cannot tell the structure apart. The semantic <H2> tag prints as nothing. Implementation notes: This is the print-side counterpart to the tag-tree heading ladder (see the normalize-heading-ladder work, commit d8eda4f). The tag ladder and the visual ladder must agree: a run styled to look like a heading must carry the matching Hn tag, and vice-versa. Preserve mode inherits the source’s visual hierarchy β€” verify it is real, not faked with a one-off large bold line. Reflow: bind each Hn to a distinct, size-ordered CSS style. Audit: flag same-level headings that render with differing size/weight, and adjacent levels that are visually identical.


Level: SHOULD Applies to: all documents Source: Clear-print consensus; Gestalt proximity; APH/CNIB spacing guidance Source strength: consensus standard Machine-checkable: partial Validation: Measure vertical gap between blocks. Confirm the gap between logical groups (e.g. section-to-section) is visibly larger than the gap within a group (line-to-line leading and intra-group spacing). Human confirms grouping matches meaning.

Related content SHOULD be grouped by whitespace so that the space between distinct groups is visibly greater than the space within a group; a label and its associated content SHOULD sit closer together than either sits to unrelated material. Pages SHOULD NOT be packed edge-to-edge to save paper at the expense of grouping.

Rationale: Proximity is the only grouping cue that survives to paper β€” there is no <Sect> boundary to announce. When everything is equidistant, a reader with a cognitive disability cannot tell what belongs with what; a label can appear to attach to the wrong value (a direct hazard for forms β€” see PRINT-FORM-012). Implementation notes: Resist β€œshrink-to-fit the extra page” pressure; that pressure is what destroys grouping whitespace and is the same force behind the print-scaling trap (PRINT-SUBSTRATE-008). Reflow: use consistent margin tokens where inter-group margin > intra-group margin. Preserve mode: leave the source spacing alone. Audit: hard to score reliably β€” treat as assistable, flag pages whose block-gap variance is near-zero (uniformly dense) for human review.


Level: SHOULD Applies to: all documents Source: Clear-print consensus; WCAG 1.3.1 intent (list structure) Source strength: consensus standard Machine-checkable: partial Validation: Confirm list items carry a visible marker (bullet glyph, number, or lettered prefix) and a consistent hanging indent so wrapped lines align under the text, not under the marker. Confirm ordered lists use printed numerals/letters (not color or an untagged pseudo-marker).

Lists SHOULD present a visible per-item marker (bullet, number, or letter) with a consistent hanging indent; the marker SHOULD NOT rely on color or an interactive/tag-only affordance to be perceivable. Ordered relationships (steps, ranked items) SHOULD use printed numbers or letters, not merely visual position.

Rationale: The <L>/<LI> tag structure is invisible on paper. Without a printed marker and indent, a list collapses into an undifferentiated paragraph, and step order β€” critical for instructions and forms β€” is lost to anyone who cannot infer it from prose alone. Implementation notes: Reflow/WeasyPrint: use real <ul>/<ol> with list-style markers; never fake bullets with a colored dash. Preserve mode: verify source bullets are actual glyphs, not decorative images with no printed fallback. This pairs with imperative-instruction language (PRINT-LANG-005) for procedural content.


Level: SHOULD Applies to: all documents Source: Clear-print / accessible-table consensus; WCAG 1.3.1 intent Source strength: consensus standard Machine-checkable: yes Validation: For any table whose body rows span a page break, confirm the header row(s) repeat at the top of each continuation page. Automatable: detect table geometry crossing a page boundary and check for a repeated header row on the following page.

When a table continues across a page break, its header row(s) SHOULD repeat at the top of every continuation page. A table that breaks across pages SHOULD NOT leave continuation rows headerless.

Rationale: On screen the <TH> scope association travels with every cell; on paper the reader on page 2 sees only anonymous columns of values. Repeating the header row is the print substitute for the Scope/Headers association a screen reader would have read aloud. Implementation notes: Reflow/WeasyPrint: mark header rows with <thead> β€” WeasyPrint repeats <thead> on each page automatically. Preserve mode: the source PDF’s fixed geometry may not repeat headers; if a preserved table breaks headerless, flag it (cannot be auto-fixed without re-laying-out). This is distinct from β€” and required in addition to β€” the tag-tree Scope we already emit. See the despanning/table work (commit be6f4d4f).


Level: SHOULD Applies to: all documents Source: Clear-print / accessible-table consensus; WCAG 1.3.1 intent Source strength: consensus standard Machine-checkable: partial Validation: Confirm header cells are visually distinguished from data cells (weight, shading meeting PRINT-COLOR-007, or ruling) and that the table has enough ruling/alignment that a reader can trace any cell back to its row and column header. Human confirms complex/nested headers are traceable.

Row and column headers SHOULD be visually distinguished from data cells (bold, a shaded band that still meets the print-contrast floor, or clear ruling) so that any data cell’s headers are visually traceable on paper. Tables with multi-level or spanned headers SHOULD add ruling or repeated sub-headers so the association survives without the tag tree.

Rationale: The Headers/Scope attributes are non-printing. A reader who cannot instantly see which cells are headers β€” especially in a wide or sparse table β€” loses the meaning of every value. Shading used to mark headers must survive B&W printing (PRINT-COLOR-003) and grayscale reflectance (PRINT-COLOR-007). Implementation notes: Reflow: style <th> distinctly and don’t rely on a background color alone (add weight or ruling for the grayscale case). Preserve mode: many source tables mark headers by color only β€” flag these; the color-only cue fails on a mono printer. Audit/ACR: cross-reference tagged <TH> cells against visual distinction; a <TH> that looks identical to a <TD> on paper is a print-layer failure even when the tag is correct.


Level: SHOULD Applies to: all documents Source: Clear-print / production consensus Source strength: consensus standard Machine-checkable: yes Validation: Compute rendered table width against the printable text-block width (page width minus margins/binding allowance, PRINT-LAYOUT-012). Flag any table that overflows the printable area or is only made to fit by auto-shrink scaling below the point-size floor (PRINT-TYPO-001).

A table SHOULD fit within the printable text block at the document’s normal point size. A table too wide to fit SHOULD be handled by an explicit strategy β€” rotate to a dedicated landscape page (PRINT-LAYOUT-013), split into linked sub-tables with repeated stub/header columns, or transpose β€” and SHOULD NOT be silently scaled below the minimum readable point size to force a fit.

Rationale: Auto-shrinking a wide table below the type floor makes it unreadable for the low-vision readers the point-size rule exists to protect; overflow clipping loses columns entirely. Neither failure is visible in the digital preview β€” it appears only on the printed sheet. Implementation notes: This intersects the print-scaling trap (PRINT-SUBSTRATE-008): a table that β€œfits” only under fit-to-printable shrink violates the point-size floor once printed. Preserve mode: measure the source table; flag overflow rather than rescale. Reflow: prefer transposition or a landscape break over horizontal scaling. Never emit shrink-to-fit as the fix.


Level: MUST Applies to: all documents Source: ADA/504 effective-communication duty (see PRINT-LEGAL-001/002/006); WCAG 1.1.1 intent Source strength: regulation (duty) + consensus (mechanism) Machine-checkable: partial Validation: For every image that carries meaning (non-decorative), confirm a visible printed caption or adjacent body text conveys the equivalent information. Automatable: detect meaningful images lacking any adjacent printed caption/description and flag. Human confirms the caption is equivalent, not merely present. Decorative images (alt="" / artifact) are exempt.

Every image that conveys information MUST have its equivalent information available in printed text β€” a visible caption, an adjacent description, or surrounding body copy β€” because alt text does not print. Decorative images MUST NOT carry a spurious caption. A chart or diagram whose data is not otherwise stated in the text MUST have a printed long description or the underlying data presented in an accessible form (see PRINT-FIDELITY-005).

Rationale: alt text lives entirely in the non-printing tag layer. A blind reader receiving the print alternate, a low-vision reader who cannot resolve fine chart detail, and anyone photocopying the page all lose 100% of image-only information unless it is in visible text. This is the single clearest case of the section’s thesis β€” the affordance evaporates on print and must be independently carried by the visual layer, and here the duty is legal, not merely ergonomic. Implementation notes: This is the highest-value link between our alt-text pipeline and print. The meaningful-alt floor we enforce on the chunked lane (commit 331160f) produces the digital alt; for a print-safe profile the same content must be surfaced visibly (caption or long-description block), not only in /Alt. Preserve mode: do NOT auto-inject captions into a fixed layout (no room); instead flag meaningful images that lack a visible caption so a human decides. Reflow: emit <figure><figcaption> and, for complex images, a visible long-description block or a link/reference to one (PRINT-FIDELITY-005). Audit/ACR: a document can be fully alt-tagged and still fail this on paper.


Level: SHOULD Applies to: all documents Source: Clear-print / accessible-document consensus Source strength: consensus standard Machine-checkable: yes Validation: Confirm multi-page documents print a visible page number on each page, preferably in β€œPage X of Y” form. Automatable: check for a per-page number in a consistent position; flag multi-page output with no printed page numbers.

Multi-page documents SHOULD print a visible page number on every page, and SHOULD use β€œPage X of Y” so a reader can detect a missing or misordered sheet. Page numbers SHOULD sit in a consistent position and SHOULD meet the body-text point-size and contrast floors.

Rationale: Paper gets shuffled, dropped, and photocopied out of order. β€œPage X of Y” lets any reader β€” and especially someone with a cognitive disability β€” confirm they have the whole document in the right sequence; the digital page-tree that guaranteed order is gone. Implementation notes: Reflow/WeasyPrint: use CSS paged-media @page counters with counter(page) / counter(pages). Preserve mode: source pagination is fixed β€” flag its absence rather than overprint. Keep numbers out of the binding gutter (PRINT-LAYOUT-012) and above the 12 pt minimum size.


Level: MAY Applies to: all documents Source: Clear-print / accessible-document consensus Source strength: consensus standard Machine-checkable: partial Validation: If running headers/footers are present, confirm they are consistent across pages, do not collide with the text block or binding gutter, and do not repeat so much material that they crowd body content. Confirm they are marked as artifacts/pagination in the tag tree so they don’t pollute reading order.

Running headers/footers MAY carry the document title, section, date, or version to aid orientation across a printed stack; when used they SHOULD be consistent in content and position across pages and SHOULD NOT encroach on the body text block or repeat so heavily that they reduce the readable area.

Rationale: Consistent running heads help a reader re-orient within a long printed document that has no scrollbar or bookmark pane. Inconsistent or bloated ones waste the readable text block and can be mistaken for body content. Implementation notes: Reflow: place in @page margin boxes; tag as Artifact/Pagination. Preserve mode: source-controlled. Ensure header/footer text still meets size/contrast floors β€” small-print version strings and dates are a common violation.


Level: MAY Applies to: all documents Source: Clear-print consensus; Gestalt separation Source strength: consensus standard Machine-checkable: no Validation: Human confirms major sections are visually separated (rule, heading + generous space-before, or a section-opening page) so section boundaries are perceivable without the tag tree. No reliable automated measure.

Major sections SHOULD be visually separated by a horizontal rule, a strong heading with generous space-before, or a fresh page, so section boundaries are perceptible on paper. Separators SHOULD NOT rely on color alone (PRINT-COLOR-004) and any rule used SHOULD meet the non-text contrast floor (PRINT-COLOR-002).

Rationale: <Sect> boundaries are non-printing. A reader with a cognitive disability especially benefits from an unambiguous β€œnew section starts here” cue that a bare paragraph break does not provide. Implementation notes: Reflow: use <hr> or page-break-before at section starts. Preserve mode: inherited. A colored band used as a divider must still read as a divider in grayscale β€” pair with weight/ruling.


Level: SHOULD Applies to: all documents Source: Print-production consensus; clear-print margin guidance Source strength: consensus standard Machine-checkable: yes Validation: Confirm all live text and fields sit within a minimum margin from every trimmed edge and clear of the binding side. Defaults to verify: outer/top/bottom margin β‰₯ 0.5 in (36 pt); bound edge β‰₯ 0.75 in (54 pt) when the document is stapled or bound. Flag any glyph or widget rect whose bbox intrudes into the margin/gutter band.

Content SHOULD keep a margin of at least 0.5 in (36 pt) from every trimmed edge, and at least 0.75 in (54 pt) on the bound edge of any stapled or bound document, so text and form fields are not lost to trimming, hole-punching, or the binding curl. Form fields and signatures in particular SHOULD NOT be placed within the binding gutter.

Rationale: Text or a signature line that runs into the binding gutter or hole-punch zone becomes unreadable or unwritable after assembly β€” a hard failure for hand-completed forms. The digital preview shows the full sheet; the bound artifact does not. Implementation notes: The converter already enforces a _PAGE_MARGIN = 36.0 pt outer margin β€” widgets are clamped to page.width βˆ’ 36 (place.py, _field_rect). That covers the outer edge but is blind to the binding side: it does not add the extra bound-edge allowance. Note this gap β€” a duplex or stapled packet needs the 54 pt bound-edge margin, which the current single 36 pt constant does not provide. Reflow: set @page { margin } accordingly and increase the inner margin for :left/:right when duplexing.


Level: SHOULD Applies to: all documents Source: Print-production / accessible-document consensus Source strength: consensus standard Machine-checkable: partial Validation: For any landscape page bound with portrait pages, confirm a consistent rotation convention (head-to-the-binding vs head-away) is used throughout and, ideally, a printed hint indicating rotation. Automatable: detect landscape pages within a majority-portrait document and flag for rotation-convention review.

When a document mixes landscape and portrait pages in one bound/stapled packet, all landscape pages SHOULD rotate in the same direction relative to the binding, and the document SHOULD indicate the intended rotation (e.g. a header oriented consistently). Mixed inconsistent rotations SHOULD be avoided.

Rationale: In a stapled packet, an inconsistently rotated landscape page forces the reader to flip the whole packet the β€œwrong” way, and a low-dexterity or low-vision reader may be unable to reorient a wide table or form at all. This is the physical-assembly counterpart to wide-table handling (PRINT-LAYOUT-007). Implementation notes: When rotating a wide table onto a landscape page as the fix for PRINT-LAYOUT-007, pick one convention (conventionally head-to-the-left / binding-on-top for a staple) and apply it to every landscape page. Preserve mode: flag mixed rotations; do not silently re-rotate. Reflow: control with @page { size: landscape } on the specific page and keep the convention uniform.


Cross-references

  • Heading visual ladder ↔ tag ladder consistency: PRINT-LAYOUT-002, 01 PRINT-TYPO-002…004.
  • Header shading survival: PRINT-LAYOUT-006 ↔ 02 PRINT-COLOR-003/007.
  • Wide-table scaling ↔ print-at-100%: PRINT-LAYOUT-007 ↔ 05 PRINT-SUBSTRATE-007/008.
  • Figure/caption duty: PRINT-LAYOUT-008 ↔ 00 PRINT-LEGAL-001/002/006, 08 PRINT-FIDELITY-005.
  • Margins/gutter for form fields: PRINT-LAYOUT-012 ↔ 04 PRINT-FORM-009/020.