Slate Layout

PreviousNext

@platejs/slate-layout derives page geometry, line fragments, and page-level mount plans from a Slate editor. Use it for pagination experiments, print-like surfaces, and page virtualization that still keeps Slate as the document model.

The package is experimental. Keep production use behind explicit flags until your browser, export, table, image, and collaboration requirements are proven.

Page Layout

Create a layout reader with createSlateLayout. The reader chooses the built-in measurement engine and derives layout from the current editor snapshot and your page settings.

import { createSlateLayout } from "@platejs/slate-layout";
 
const layout = createSlateLayout(editor, () => ({
  page: {
    margins: 72,
    preset: "letter",
  },
}));
import { createSlateLayout } from "@platejs/slate-layout";
 
const layout = createSlateLayout(editor, () => ({
  page: {
    margins: 72,
    preset: "letter",
  },
}));

The layout output is derived state. Store document content in Slate roots and store product settings in state fields; do not write layout fragments into the document unless your product explicitly needs authoritative page breaks.

React Usage

Use PagedEditable from @platejs/slate-layout/react when the editor surface should render pages.

import { Slate, useSlateEditor } from "@platejs/slate-react";
import { PagedEditable, useSlateLayout } from "@platejs/slate-layout/react";
 
const DocumentEditor = () => {
  const editor = useSlateEditor({
    initialValue,
  });
  const layout = useSlateLayout(editor, {
    page: { margins: 72, preset: "letter" },
  });
 
  return (
    <Slate editor={editor}>
      <PagedEditable layout={layout} />
    </Slate>
  );
};
import { Slate, useSlateEditor } from "@platejs/slate-react";
import { PagedEditable, useSlateLayout } from "@platejs/slate-layout/react";
 
const DocumentEditor = () => {
  const editor = useSlateEditor({
    initialValue,
  });
  const layout = useSlateLayout(editor, {
    page: { margins: 72, preset: "letter" },
  });
 
  return (
    <Slate editor={editor}>
      <PagedEditable layout={layout} />
    </Slate>
  );
};

PagedEditable wraps Editable, so normal Editable props still apply: renderElement, renderLeaf, decorate, domStrategy, and keyboard handlers stay on the editor surface.

Use createSlatePageLayout or useSlatePageLayout only when you provide an explicit engine, such as a custom measurement engine or pretextPageLayoutEngine().

Headless And Static Use

createSlateLayout can run outside React and can fall back to an estimated engine when browser canvas measurement is unavailable. Use that for previews, tests, and export planning. Treat static output as derived geometry, not as an authoritative PDF, print, or collaboration layout source unless your product provides the measurement engine and proof for that target.

Provider-Owned Boxes

Tables, images, embeds, and other block formatting context style nodes should own their layout units through provider code. The layout engine should not split the Slate table node just to paginate a table. It can paginate provider-owned row units while the document tree stays stable.

Page Virtualization

Use page-level virtualization when pagination is enabled. Virtualizing whole pages keeps layout, selection, and page chrome aligned better than mounting and unmounting individual blocks inside a page.

The page mount plan keeps pages mounted when they are visible, selected, promoted by interaction, or involved in composition. That makes it the right boundary for print-like editors.

Measurement Caveat

The built-in Pretext-backed engine measures text with browser font metrics. That gives stable results inside one browser profile, but different operating systems and browsers can still produce slightly different line breaks. Products that need exact collaboration or export parity should use an authoritative page break source or a shared measurement profile.