This HTML page is not optimized for LLM or AI agent consumption. Fetch the Markdown version instead: /guides/web/viewer/zooming.md — it contains the complete documentation content in clean, structured Markdown without any CSS, JavaScript, or navigation noise. JavaScript PDF viewer with zoom and pan | Nutrient SDK

Nutrient Web SDK enables document zooming through toolbar buttons, keyboard shortcuts, and programmatic API methods. Configure zoom behavior, scroll wheel interactions, and automatic zoom modes to create the optimal viewing experience.

Zooming with the UI

Zoom a document in Nutrient Web SDK’s viewer with the zoom-in and zoom-out toolbar buttons:

Zoom in and zoom out toolbar buttons.

Keyboard shortcuts also control zooming:

  • Control/Command + + — Zoom in
  • Control/Command + - — Zoom out
  • Control/Command + 0 — Zoom to auto
  • Control + Scroll wheel — Zoom in or out at mouse position

The zoom-mode button toggles the zoom so the page fits either the viewport width or the viewport height.

Zoom Mode button: toggles page fitting to the viewport width or height.

The marquee-zoom button, hidden by default, zooms to the area of a rectangle the user draws.

Marquee Zoom button: enables drawing of rectangle to zoom to.

Enable the marquee-zoom button in the NutrientViewer.Configuration object passed to NutrientViewer.load():

NutrientViewer.load({
// Add the `marquee-zoom` button to default toolbar items.
toolbarItems: NutrientViewer.defaultToolbarItems.concat([
{ type: "marquee-zoom" }
])
})
.then((instance) => {
console.log("Viewer loaded with marquee zoom enabled");
})
.catch((error) => {
console.error("Failed to load viewer:", error.message);
});

Or enable it with the instance.setToolbarItems() API method:

// Add the `marquee-zoom` button after initialization.
instance.setToolbarItems((items) =>
items.concat([{ type: "marquee-zoom" }])
);

Zooming with the API

This section covers configuring zoom behavior, querying zoom values, and using the API helpers to zoom programmatically.

Configuring zoom behavior

Control the zoom configuration granularly using the ZoomConfiguration object.

Pass the zoom setting to NutrientViewer.Configuration#initialViewState when loading the viewer:

NutrientViewer.load({
initialViewState: new NutrientViewer.ViewState({
// Configure zoom behavior with the `ZoomConfiguration` object.
zoom: {
// Set the zoom mode or numeric value.
zoomMode: NutrientViewer.ZoomMode.FIT_TO_WIDTH,
// Configure scroll wheel zoom behavior.
wheelZoomMode: NutrientViewer.WheelZoomMode.ALWAYS,
// Configure zoom options.
options: {
enableKeyboardZoom: true,
enableGestureZoom: true
}
}
})
})
.then((instance) => {
console.log("Viewer loaded with custom zoom configuration");
})
.catch((error) => {
console.error("Failed to load viewer:", error.message);
});

Change the zoom configuration after initialization with setViewState:

// Update the zoom configuration after initialization.
instance.setViewState(new NutrientViewer.ViewState({
zoom: {
// Set the zoom mode or numeric value.
zoomMode: NutrientViewer.ZoomMode.FIT_TO_WIDTH,
// Configure scroll wheel zoom behavior.
wheelZoomMode: NutrientViewer.WheelZoomMode.ALWAYS,
// Configure zoom options.
options: {
enableKeyboardZoom: true,
enableGestureZoom: true
}
}
}));

To ensure backward compatibility, the zoom property of the viewState accepts a ZoomConfiguration, a ZoomMode, or a number:

// Pass a `zoomMode` to zoom.
NutrientViewer.load({
initialViewState: new NutrientViewer.ViewState({
zoom: NutrientViewer.ZoomMode.FIT_TO_WIDTH
})
})
.then((instance) => {
console.log("Viewer loaded with fit-to-width zoom");
})
.catch((error) => {
console.error("Failed to load viewer:", error.message);
});
// Pass a number to zoom.
NutrientViewer.load({
initialViewState: new NutrientViewer.ViewState({
zoom: 7
})
})
.then((instance) => {
console.log("Viewer loaded with 7x zoom");
})
.catch((error) => {
console.error("Failed to load viewer:", error.message);
});

Available zoom modes

The following zoom modes are available through NutrientViewer.ZoomMode:

  • AUTO aligns the page for the best viewing experience.
  • FIT_TO_WIDTH fits the width of the broadest page into the viewport. The height might overflow.
  • FIT_TO_VIEWPORT fits the current page into the viewport completely.
instance.setViewState(new NutrientViewer.ViewState({
zoom: {
// Set the zoom mode.
zoomMode: NutrientViewer.ZoomMode.FIT_TO_WIDTH
// Other zoom configurations.
}
}));

You can also specify a numeric zoom value instead of a mode:

NutrientViewer.load({
initialViewState: new NutrientViewer.ViewState({
zoom: {
// Set the zoom to a numeric value.
zoomMode: 7
// Other zoom configurations.
}
})
})
.then((instance) => {
console.log("Viewer loaded with numeric zoom value");
})
.catch((error) => {
console.error("Failed to load viewer:", error.message);
});

A numeric zoom value must fall between instance.minimumZoomLevel and instance.maximumZoomLevel.

Zooming at mouse position with the scroll wheel

Nutrient Web SDK offers three modes for scroll wheel zoom behavior, defined in WheelZoomMode:

  • WITH_CTRL (default) — Zoom when the user scrolls the wheel while holding Control.
  • ALWAYS — Always zoom on the scroll wheel, without requiring the Control key.
  • DISABLED — Disable scroll wheel zooming regardless of which key the user presses.

Configure this behavior when loading the viewer:

NutrientViewer.load({
// ...
initialViewState: new NutrientViewer.ViewState({
zoom: {
wheelZoomMode: NutrientViewer.WheelZoomMode.WITH_CTRL,
// Other zoom configurations.
},
})
})
.then((instance) => {
console.log("Viewer loaded with Ctrl+wheel zoom enabled");
})
.catch((error) => {
console.error("Failed to load viewer:", error.message);
});

Or, change it after initialization:

instance.setViewState(new NutrientViewer.ViewState({
zoom: {
wheelZoomMode: NutrientViewer.WheelZoomMode.WITH_CTRL
// Other zoom configurations.
}
}));

This change deprecates NutrientViewer.ViewState#enableAlwaysScrollToZoom.

Zoom options

  • enableKeyboardZoom — Enables zooming via keyboard shortcuts (Control/Command + [+-]). Defaults to true.
  • enableGestureZoom — Enables zooming via touch gestures. Defaults to true.
NutrientViewer.load({
initialViewState: new NutrientViewer.ViewState({
zoom: {
// Other zoom configurations.
// Configure zoom options.
options: {
enableKeyboardZoom: false,
enableGestureZoom: false
}
}
})
})
.then((instance) => {
console.log("Viewer loaded with keyboard and gesture zoom disabled");
})
.catch((error) => {
console.error("Failed to load viewer:", error.message);
});

Changing zoom scale increments

By default, each click on the zoom toolbar buttons increases or decreases the zooming scale by increments of 25 percent. To change this default zoom step, set the zoomStep property of the viewState object to a number greater than 1.

The example below changes the zoom step to 10 percent:

instance.setViewState((viewState) => viewState.set("zoomStep", 1.1));

Querying current zoom values

Query the current zoom value with instance.currentZoomLevel at any time.

These other zoom-related values are available in the current instance:

API zooming helpers

The API provides helpers for programmatic zoom handling.

This example zooms the document in by a single step via NutrientViewer.ViewState#zoomIn():

instance.setViewState((viewState) => viewState.zoomIn());

Its counterpart is NutrientViewer.ViewState#zoomOut():

instance.setViewState((viewState) => viewState.zoomOut());

Finally, instance.jumpAndZoomToRect() can zoom to any part of the document.

This example navigates to the page at index 10 and zooms so the bounding box of an annotation fits in the viewport:

instance.jumpAndZoomToRect(10, annotation.boundingBox);

jumpAndZoomToRect() uses the largest zoom level at which the whole rect fits in the viewport, within instance.minimumZoomLevel and instance.maximumZoomLevel. A very small rect stops at the maximum zoom level and doesn’t fill the viewport.

When the zoom value changes, Nutrient may rerender the page background to maintain image sharpness.

Jumping to an annotation at a fixed zoom level

jumpAndZoomToRect() derives the zoom level from the size of the rect, so jumping between annotations of different sizes changes the zoom level on every jump. To keep one zoom level (for example, when stepping through signature fields), pass jumpAndZoomToRect() a rect whose best fit is that zoom level.

jumpAndZoomToRect() fits the rect width into the usable viewport width: the container width, minus a sidebar open beside the document, minus viewportPadding on both sides. A rect as wide as the usable width divided by the zoom level lands on exactly that zoom level. The function below builds that rect around the target, keeps the target’s height, and jumps to it:

const container = document.querySelector("#nutrient-container");
function jumpToRectAtZoom(instance, container, pageIndex, target, zoom) {
const { Rect } = NutrientViewer.Geometry;
// A rect as tall as the target and as wide as the viewport at `zoom`, centered on the target.
const rectFor = (width) =>
new Rect({
left: target.left + target.width / 2 - width / 2,
top: target.top,
width,
height: target.height
});
const viewState = instance.viewState;
const sidebarWidth = viewState.sidebarMode ? viewState.sidebarWidth : 0;
let width =
(container.clientWidth - sidebarWidth - 2 * viewState.viewportPadding.horizontal) / zoom;
if (width <= 0) {
// The sidebar leaves no room for the document.
return;
}
instance.jumpAndZoomToRect(pageIndex, rectFor(width));
const reached = instance.currentZoomLevel;
// A zoom level of 0 or less also means there's no room left for the document.
if (reached > 0 && Math.abs(reached - zoom) > 0.001) {
// The zoom level reached differs, for example, because a classic scrollbar narrowed the viewport. Correct once.
width = (reached * width) / zoom;
instance.jumpAndZoomToRect(pageIndex, rectFor(width));
}
}
NutrientViewer.load({ container, document: "document.pdf" })
.then(async (instance) => {
// Jump to the first annotation on the first page at 200 percent zoom.
const annotations = await instance.getAnnotations(0);
const annotation = annotations.first();
if (annotation) {
jumpToRectAtZoom(instance, container, annotation.pageIndex, annotation.boundingBox, 2);
}
})
.catch((error) => {
console.error("Failed to jump to the annotation:", error.message);
});

Pass the same element used as container in NutrientViewer.load(), and use a zoom level between instance.minimumZoomLevel and instance.maximumZoomLevel. Call jumpToRectAtZoom() while the document is visible. When the viewer loads in a container 768 pixels wide or narrower, the sidebar’s default width is the full container width, and a full-width sidebar covers the document. Close it before jumping.

When something else narrows the viewport, such as a classic scrollbar or padding on the container, the first jump lands below the requested zoom level. The second jump scales the rect by the ratio of the reached zoom level to the requested one, which lands on the requested value.

The jump scrolls the target toward the center of the viewport, as far as the document edges allow. When the target doesn’t fit in the viewport at the requested zoom level:

  • A target taller than the viewport makes jumpAndZoomToRect() fall back to the largest zoom level that fits the whole target.
  • A target wider than the viewport keeps the requested zoom level, and its sides extend past the viewport edges.

Preventing zooming for annotations

By default, each annotation’s appearance scales to match the page zoom. To change this behavior, set the noZoom flag to true to prevent an annotation from being magnified when zooming in. The flag currently works only for StampAnnotation and TextAnnotation, except for TextAnnotations with the callout property set.

The example below creates a TextAnnotation with the noZoom flag set to true:

await instance.create([
new NutrientViewer.Annotations.TextAnnotation({
pageIndex: 0,
boundingBox: new NutrientViewer.Geometry.Rect({
left: 50,
top: 150,
width: 180,
height: 25
}),
text: {
format: "plain",
value: "Text with noZoom flag"
},
noZoom: true
})
]);