Zoom and fit to screen

Fit the document to the viewport, control zoom from your UI with useZoom, and let the comments pane shrink the page instead of covering it.

The editor fits the page to its container by default. A container wide enough for the page renders at 100%. A narrower container shrinks the document instead of creating a horizontal scrollbar.

The two modes

Zoom has a value and a mode. The value is the scale the pages paint at; the mode is where that value comes from.

ModeBehavior
'auto' (default)Fit the page width, between 50% and 100%. Shrinks a page that does not fit, leaves one that does.
{ type: 'fit', fit: 'pageWidth' }Fit the page width in both directions, so a wide window magnifies the page.
{ type: 'fixed' }Hold whatever zoom is set to. This keeps a fixed scale (the behavior before fit modes).
<DocxEditor document={bytes} />                          {/* auto */}
<DocxEditor document={bytes} zoomMode={{ type: 'fit', fit: 'pageWidth' }} />
<DocxEditor document={bytes} zoom={1} zoomMode={{ type: 'fixed' }} />

Passing zoom on its own also means fixed, so an app that pinned a scale keeps it.

Fit mode updates when the container size changes. Resizing the window, opening the comments pane, or docking the navigation pane changes the space beside the page. The engine updates the scale without additional host code.

Setting a level ends the fit. A fixed zoom replaces fit mode. Container resize must not override an explicit scale.

Driving it yourself

useZoom returns zoom state and controls in one hook.

import { useZoom } from '@docx-editor.dev/react';

function ZoomControl() {
  const { zoom, isFit, auto, zoomIn, zoomOut, canZoomIn, canZoomOut } = useZoom();

  return (
    <div>
      <button onClick={zoomOut} disabled={!canZoomOut}>
        &minus;
      </button>
      <span>{Math.round(zoom * 100)}%</span>
      <button onClick={zoomIn} disabled={!canZoomIn}>
        +
      </button>
      <button onClick={auto} aria-pressed={isFit}>
        Fit
      </button>
    </div>
  );
}
MemberWhat it does
zoomThe resolved scale. 1 is 100%.
mode, isFitWhere the scale came from. Render a control's selected state from these, not from zoom.
setZoom(n)A fixed scale. Leaves any fit.
setMode(m)'auto', a fit, or { type: 'fixed' }.
auto(), fitToWidth()The two fits, by name.
reset()Reset to fixed 100% zoom.
zoomIn(), zoomOut()Move to the next preset in levels.
canZoomIn, canZoomOutWhether a higher or lower preset remains.

Render the selected state from mode, not from zoom. A menu that ticks the level matching the percentage marks "75%" as selected while fit mode still owns the scale.

The packaged toolbar's zoom control already does all of this: Automatic and Fit width sit above the preset levels, and the tick follows the mode rather than the percentage.

It ticks those two modes and the preset levels — the modes the menu can select. A fit with bounds of your own is not one of them, so the menu shows the resolved percentage with nothing ticked, rather than marking a preset that would replace custom fit bounds on click.

Comments, and narrow screens

The comments rail reserves a gutter beside the page. Under a fit that gutter comes out of the document's width, so opening comments shrinks the page rather than pushing it off screen: the two sit side by side and both stay readable.

Below a container width, reserving the rail width no longer keeps the page readable. The rail takes a fixed 316px whether or not the container can spare it. On a phone with comments open, fit would shrink the page below a readable width. So 'auto' has a floor of 50%: below that the page keeps a legible size and the container scrolls sideways, which matches the usual layout response when content exceeds the container.

Set your own floor if 50% is not where you want it:

<DocxEditor document={bytes} zoomMode={{ type: 'fit', fit: 'pageWidth', minZoom: 0.35 }} />

Without an adapter

Zoom APIs are on the engine. Every host calls the same methods:

editor.setZoomMode('auto');
editor.getZoom(); // 0.79 on a container too narrow for the page
editor.getZoomMode(); // { type: 'fit', fit: 'pageWidth', minZoom: 0.5, maxZoom: 1 }

editor.setZoom(1.5); // leaves the fit
editor.getZoomMode(); // { type: 'fixed' }

snapshot() carries zoom and zoomMode, and both fire on selectionChange — including when the editor refits itself after a resize, so a subscriber never shows a stale percentage.

On this page