Private betav0.1.0
Docs
Format developer documentation

Frame

A bounded sub-region of a Layout that a Flow paginates against instead of the page.

A Frame is the boundary that Format measures a Flow's content against. When a Flow's content overflows its Frame, pagination rolls over to a new page.

A Frame is a piece of Layout scaffolding that defines a measured region. Format measures the region's bounds, and the Flows inside it use those bounds as their overflow boundary.

By default, a Flow's overflow boundary is the page itself. That's enough for the common "fill the page until it's full" case, and most Layouts don't need an explicit Frame.

Use a Frame when a Flow needs to be constrained to a sub-region (a notes aside capped at a fixed height, a half-page chart area, a sidebar that paginates independently of the body), or when other parts of the Layout need to react to a measured size. A Frame's measured dimensions are exposed to sibling content so it can react to the region's size.

Fields

NameTypeDescription
idRequired
stringUnique identifier within the owning Layout.

Example

Below, an <aside> element is declared as a Frame. Unlike most types, Frame has no SDK component: you mark a plain element with data-type="frame" and a data-id directly, in any SDK or in HTML. The Flow inside it overflows against the Frame's bounded height rather than the full page.

export const doc = () => (
  <Document title="Invoice #1234">
    <Layout id="invoice" width={793.71} height={1122.52}>
      <main>
        <Flow>
          <p>Invoice for Horizon Studios.</p>
        </Flow>
      </main>

      <aside data-type="frame" data-id="notes-region" style={{ maxHeight: '6cm' }}>
        <Flow>
          <h2>Notes</h2>
          <Stream>
            <p>Payment due within 30 days.</p>
          </Stream>
        </Flow>
      </aside>
    </Layout>
  </Document>
)
<template>
  <Document title="Invoice #1234">
    <Layout id="invoice" :width="793.71" :height="1122.52">
      <main>
        <Flow>
          <p>Invoice for Horizon Studios.</p>
        </Flow>
      </main>

      <aside data-type="frame" data-id="notes-region" style="max-height: 6cm">
        <Flow>
          <h2>Notes</h2>
          <Stream>
            <p>Payment due within 30 days.</p>
          </Stream>
        </Flow>
      </aside>
    </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">
    <main>
      <template data-type="flow">
        <p>Invoice for Horizon Studios.</p>
      </template>
    </main>

    <aside data-type="frame" data-id="notes-region" style="max-height: 6cm">
      <template data-type="flow">
        <h2>Notes</h2>
        <template data-type="stream">
          <p>Payment due within 30 days.</p>
        </template>
      </template>
    </aside>
  </template>
</template>

Any HTML element with layout can be a Frame: <div>, <table>, <p>, <section>, and so on.

Useful

A Frame needs a bounded height

A Frame only paginates content if its own height is bounded. Give it a height or max-height in CSS, or a definite size from a flex or grid parent. Without one, the Frame grows to fit its content, so the Flow inside it never overflows to a new page.

Usage

A Flow overflows against its nearest ancestor Frame, or the page when no Frame encloses it. Place a Flow inside a data-type="frame" element to bound where it breaks. Declare a Frame when:

  • A Flow should paginate against a bounded region, not the full page. A notes aside capped at a fixed height or a half-page chart area both fit this case. Wrap that region in a Frame, and the Flow overflows when the Frame fills rather than when the page does.
  • Other parts of the page need to react to a measured size. Frame dimensions are published as CSS variables (e.g. --frame-notes-region-height) so siblings can size against them. See the DOM contract for the full list.
  • Two Flows need different page-fill boundaries on the same page. Give each Flow its own Frame, and each breaks when its own region fills.

When none of those conditions apply, the page is the default boundary and no explicit Frame is needed.

Was this page helpful?