Work in progress — this reference is being written in the open. Unfinished pages are excluded from search engines.
Paged · IDML Reference
Tables

Tables in the text flow

What it means for a table to be anchored in a story's paragraph — how it draws where the flow reaches it, breaks across threaded frames, and repeats its header and footer rows.

Pro· explanation

An IDML table is part of the text flow: it draws where its host paragraph lands, breaks across threaded frames, and can repeat its header and footer rows.

In short: A <Table> is an inline element anchored in a story's paragraph, so it has no position of its own — it draws wherever the host paragraph lands as the story flows down its text frame. When a table is taller than the frame it starts in, it splits across the threaded frame chain, filling each frame and continuing the remaining rows in the next. Its header rows can reappear at the top of each continuation frame and its footer rows at the bottom of each frame but the last. This page explains where a table goes, as opposed to what it is.

The table model and its rows, columns, and cells describe what a table is. This page is about where it goes — and the answer is the thread that ties the whole chapter together: a table is part of the text flow.

A table rides on a paragraph

A <Table> is an inline element. It sits inside a <CharacterStyleRange>, inside a <ParagraphStyleRange>, inside a story — the same place a run of text sits. The run that hosts the table carries no text of its own; its job is simply to be the anchor the table rides on.

<Story Self="ustory">
  <ParagraphStyleRange AppliedParagraphStyle="ParagraphStyle/$ID/[No paragraph style]">
    <CharacterStyleRange AppliedCharacterStyle="CharacterStyle/$ID/[No character style]">
      <Table Self="utable" …> … </Table>
    </CharacterStyleRange>
  </ParagraphStyleRange>
</Story>

This is why a table has no position of its own. It draws where the host paragraph lands. The story flows down its text frame — paragraph after paragraph, top to bottom — and when the flow reaches the paragraph that hosts the table, the renderer lays the table's grid out there, starting at the left edge of the text column and running down from the current vertical cursor. Whatever follows the table in the story resumes below it. Move the host paragraph, and the table moves with it; you never position a table directly.

Breaking across threaded frames

A story can be threaded through a chain of frames, so its text flows from one frame into the next. A table caught in that flow can be taller than the frame it starts in. When that happens, the table splits: the renderer fills the first frame with as many rows as fit, then continues the remaining rows at the top of the next frame in the chain, and so on down the chain.

This works for the common case — body rows flowing from one frame into the next — but the splitter is deliberately simple. A single row taller than a whole frame is not itself split across the break; the table only advances to a new frame when there is a next frame in the chain to advance into; and the row's KeepWithNextRow constraint is not consulted when choosing where to break.

Supportedtable break across threaded frames — common case; row-level keep-together not yet honoured

Repeating headers and footers

When a table breaks across frames, its header rows can reappear at the top of each continuation frame, and its footer rows at the bottom of each frame but the last, so a reader of any frame sees the column headings. The RepeatingHeader and RepeatingFooter booleans on the <Table> control this. Both default to repeating when absent; an explicit false makes the header or footer appear only once, in its original position.

The renderer implements both: when repetition is on, it reserves space for the replayed footer at the bottom of each non-last frame and re-draws the header rows at the top of each continuation. The placement is the straightforward once-per-frame replay; the finer BreakHeaders / BreakFooters placement modes (per text column versus per page) and the SkipFirstHeader / SkipLastFooter flags that IDML can also carry are not yet read.

Supportedrepeating header/footer — once-per-frame replay; BreakHeaders/BreakFooters modes and SkipFirst/SkipLast not yet read

Why this matters

Because a table lives in the flow rather than on the page, everything you know about stories applies to it. Its width follows the text column. Its vertical position follows the paragraphs above it. Its continuation follows the frame chain. The grid, the cells, and the borders from the other pages are what draws; the flow is where. The two together are the whole picture of an IDML table.

Frequently asked questions

How is a table positioned on the page? A table is not positioned directly. It rides on a host paragraph and draws where that paragraph lands — at the left edge of the text column, running down from the current vertical cursor. Move the host paragraph and the table moves with it.

What happens when a table is taller than its frame? If the story is threaded through a chain of frames, the table splits: the renderer fills the first frame with as many rows as fit, then continues the remaining rows at the top of the next frame, and so on down the chain. A single row taller than a whole frame is not itself split, and the table only advances when there is a next frame to advance into.

Do header and footer rows repeat when a table breaks across frames? Yes, by default. The RepeatingHeader and RepeatingFooter booleans on the <Table> control it; both default to repeating when absent, and an explicit false makes the header or footer appear only once. The renderer redraws the header at the top of each continuation frame and reserves space for the footer at the bottom of each non-last frame.

Is KeepWithNextRow honoured when choosing where a table breaks? No. The break splitter is deliberately simple and does not consult a row's KeepWithNextRow constraint, nor the finer BreakHeaders / BreakFooters placement modes or SkipFirstHeader / SkipLastFooter flags, when deciding where to break.

On this page