Thumbnail Plugin

The Thumbnail Plugin adds a classic sidebar view with small, clickable previews of each page. It’s an intuitive way for users to get an overview of the document and quickly jump to a specific page.

For optimal performance with long documents, the plugin uses virtualization, rendering only the thumbnail images that are currently visible in the sidebar’s viewport.

Installation

This plugin needs the Render plugin to work. The Scroll plugin is optional but required for the auto-scroll feature.

npm install @embedpdf/plugin-thumbnail @embedpdf/plugin-render @embedpdf/plugin-scroll

Registration

Import ThumbnailPluginPackage and its dependencies, then add them to the plugins array. The dependencies should be registered before the thumbnail plugin.

import { createPluginRegistration } from '@embedpdf/core' import { EmbedPDF } from '@embedpdf/core/react' // ... other imports import { RenderPluginPackage } from '@embedpdf/plugin-render/react' import { ScrollPluginPackage } from '@embedpdf/plugin-scroll/react' import { ThumbnailPluginPackage } from '@embedpdf/plugin-thumbnail/react' const plugins = [   // ... other essential plugins   createPluginRegistration(LoaderPluginPackage, { /* ... */ }),   createPluginRegistration(ViewportPluginPackage),   // Register dependencies first   createPluginRegistration(RenderPluginPackage),   createPluginRegistration(ScrollPluginPackage),   // Register and configure the thumbnail plugin   createPluginRegistration(ThumbnailPluginPackage, {     width: 120, // Sets the width of thumbnail images   }), ]

Usage

The plugin features two main components: <ThumbnailsPane /> (the virtualized container) and <ThumbImg /> (for rendering the page image).

Building a Thumbnail Sidebar

You’ll typically place <ThumbnailsPane /> in a sidebar next to your main <Viewport />. It uses a render prop pattern, where you provide a function as its child. This function gets called for each visible thumbnail, receiving metadata (m) about its dimensions and position. You then use this metadata to style your thumbnail container, inside of which you’ll render the <ThumbImg meta={m} /> component.

To handle navigation, you can use the useScroll hook to get the scrollToPage function and the currentPage for highlighting the active thumbnail.

Using the meta Object

The meta object passed to your render prop contains pre-calculated values that are crucial for the plugin’s virtualization and scrolling logic to work correctly. Here’s a breakdown of the key properties and how to use them:

  • m.top: The absolute vertical position of the thumbnail wrapper. You must apply this to your wrapper element’s top style.
  • m.wrapperHeight: The total height of the thumbnail’s container, including the image, label, and padding. You must apply this to your wrapper element’s height style.
  • m.width & m.height: The dimensions of the thumbnail image itself. Apply these to the element that contains the <ThumbImg /> component.
  • m.labelHeight: The height reserved for the page label.
  • m.padding: The padding around the thumbnail image.

By correctly applying top and wrapperHeight, you ensure that the virtualized layout is rendered without gaps or overlaps.

import { useScroll } from '@embedpdf/plugin-scroll/react'; import { ThumbnailsPane, ThumbImg } from '@embedpdf/plugin-thumbnail/react'; const ThumbnailSidebar = () => { const { state, provides } = useScroll(); return ( <ThumbnailsPane> {(m) => { const isActive = state.currentPage === m.pageIndex + 1; return ( <div key={m.pageIndex} style={{ position: 'absolute', top: m.top, height: m.wrapperHeight, // ... other wrapper styles }} onClick={() => provides?.scrollToPage({ pageNumber: m.pageIndex + 1 })} > <div style={{ border: `2px solid ${isActive ? 'blue' : 'grey'}`, width: m.width, height: m.height, }} > <ThumbImg meta={m} /> </div> <span style={{ height: m.labelHeight }}> {m.pageIndex + 1} </span> </div> ); }} </ThumbnailsPane> ); };

Live Example

This example shows a complete PDF viewer with a thumbnail sidebar. Clicking a thumbnail will navigate the main document, and the active thumbnail is highlighted with a blue border.

Loading PDF Engine...

API Reference

Configuration (ThumbnailPluginConfig)

OptionTypeDescription
widthnumberThe width of the thumbnail image in CSS pixels. Default: 120
gapnumberThe vertical space between each thumbnail in CSS pixels. Default: 8
buffernumberThe number of off-screen thumbnails to render above and below the visible area. Default: 3
labelHeightnumberThe height reserved for the page number label below the image. Default: 16
autoScrollbooleanIf true, the sidebar automatically scrolls to keep the current page’s thumbnail in view. Default: true
scrollBehaviorstringThe scroll animation ('smooth' or 'auto'). Default: 'smooth'
imagePaddingnumberPadding inside the thumbnail’s border, around the image itself. Default: 0
paddingYnumberVertical padding for the top and bottom of the entire thumbnail container. Default: 0

Component: <ThumbnailsPane />

The virtualized scroll container for the thumbnails.

PropTypeDescription
children(meta: ThumbMeta) => ReactNode(Required) A render prop function that receives thumbnail metadata and returns the component for a single thumbnail.

Component: <ThumbImg />

Renders the rasterized image for a single thumbnail.

PropTypeDescription
metaThumbMeta(Required) The metadata object for the thumbnail, provided by the <ThumbnailsPane /> render prop.

Hook: useThumbnailCapability()

Provides access to the plugin’s methods, though direct interaction is rarely needed due to the autoScroll feature.

Returns

PropertyTypeDescription
providesThumbnailCapability | nullAn object with methods to interact with the plugin, or null if not ready.

ThumbnailCapability Methods

MethodDescription
scrollToThumb(pageIndex)Programmatically scrolls the thumbnail sidebar to make the specified page thumbnail visible.
renderThumb(pageIndex, dpr)A low-level method to manually trigger the rendering of a specific thumbnail image. Returns a Task<Blob>.
Last updated on October 27, 2025

Need Help?

Join our community for support, discussions, and to contribute to EmbedPDF's development.