# Fullscreen

Show the document fullscreen with the browser's Fullscreen API, an in-page overlay, or inside your own dialog.

## Basics

The fullscreen button puts the viewer into browser fullscreen; <kbd>Esc</kbd> or the button leaves it.

**Demo: Native fullscreen**

```tsx
import { PdfViewer } from '@kingtech/react-pdf-viewer';

export default function Demo() {
  // The fullscreen button uses the browser Fullscreen API; Esc leaves it.
  return <PdfViewer source="/samples/letter-3pages.pdf" />;
}
```

The button's label and icon follow the state, and the document is never reloaded when fullscreen changes. <kbd>f</kbd> toggles fullscreen from the keyboard.

### Overlay

`fullscreenMode="overlay"` covers the browser window with a fixed layer instead. Focus stays inside the viewer, the page behind stops scrolling, and <kbd>Esc</kbd> closes it.

**Demo: Overlay fullscreen**

```tsx
import { PdfViewer } from '@kingtech/react-pdf-viewer';

export default function Demo() {
  // A full-viewport layer inside the page: focus is trapped, the page behind stops scrolling.
  return <PdfViewer source="/samples/letter-3pages.pdf" fullscreenMode="overlay" />;
}
```

Where element fullscreen is unavailable, `native` mode falls back to the overlay automatically.

### Controlled by your app

Passing `fullscreen` selects `fullscreenMode="controlled"`: the viewer switches to its fullscreen layout and your component decides how to present it, for example in your own dialog.

**Demo: Fullscreen inside your own dialog**

```tsx
import { PdfViewer } from '@kingtech/react-pdf-viewer';
import { useState } from 'react';

export default function Demo() {
  const [fullscreen, setFullscreen] = useState(false);

  const viewer = (
    <PdfViewer
      source="/samples/letter-3pages.pdf"
      fullscreen={fullscreen}
      onFullscreenChange={setFullscreen}
    />
  );

  // `fullscreen` is passed, so the mode is "controlled": the viewer switches to its fullscreen
  // layout and this component decides how to present it. The viewer stays mounted.
  return fullscreen ? (
    <div
      role="dialog"
      aria-modal="true"
      aria-label="Document"
      style={{ position: 'fixed', inset: 0, zIndex: 1000, background: '#fff', overflowY: 'auto' }}
    >
      {viewer}
    </div>
  ) : (
    viewer
  );
}
```

| Mode                                     | Who presents fullscreen         | Use when                                                 |
| ---------------------------------------- | ------------------------------- | -------------------------------------------------------- |
| `native` (default without `fullscreen`)  | The browser                     | You want real fullscreen                                 |
| `overlay`                                | The viewer, as an in-page layer | Embedded pages, or iframes without fullscreen permission |
| `controlled` (default with `fullscreen`) | Your app                        | Your design system already has a full-screen dialog      |

## Customization

The fullscreen background, padding and stacking order are CSS variables, and both button labels can be renamed.

**Demo: A dark “focus mode”**

```tsx
import { PdfViewer } from '@kingtech/react-pdf-viewer';
import type { CSSProperties } from 'react';

const style = {
  '--rpv-fullscreen-bg': '#0f172a',
  '--rpv-toolbar-bg': '#334155',
  '--rpv-viewport-padding-fullscreen': '48px',
} as CSSProperties;

export default function Demo() {
  return (
    <PdfViewer
      source="/samples/letter-3pages.pdf"
      fullscreenMode="overlay"
      labels={{ enterFullscreen: 'Focus mode', exitFullscreen: 'Leave focus mode' }}
      style={style}
    />
  );
}
```

See `--rpv-fullscreen-bg`, `--rpv-viewport-padding-fullscreen` and `--rpv-overlay-z-index` in the [CSS variables reference](https://react-pdf-viewer-chi.vercel.app/react-pdf-viewer/api/css-variables/) and the [customization guide](https://react-pdf-viewer-chi.vercel.app/react-pdf-viewer/customization/).

## Advanced / escape hatch

`toggleFullscreen()` and the `fullscreen` value on the [imperative API](https://react-pdf-viewer-chi.vercel.app/react-pdf-viewer/imperative-api/) work in every mode. `onFullscreenChange` reports changes made by the browser too, such as pressing <kbd>Esc</kbd> in native fullscreen.

## Limitations

- **Native fullscreen needs permission inside iframes.** A cross-origin iframe must allow it (`allow="fullscreen"`); otherwise the viewer falls back to the overlay, which covers only the iframe. Workaround: add the `allow` attribute, or open the document in a top-level page.
- **The overlay is confined by transformed ancestors.** A CSS `transform`, `filter` or `contain` on an ancestor makes the fixed layer cover that ancestor instead of the window. Workaround: use `controlled` mode and render your dialog outside the transformed element.
- **Some mobile browsers do not support element fullscreen.** The viewer falls back to the overlay where the Fullscreen API is unavailable; this fallback has not been verified on every mobile browser.

## API

- [FullscreenMode](https://react-pdf-viewer-chi.vercel.app/react-pdf-viewer/api/fullscreen-mode.md)
- [PdfViewerProps](https://react-pdf-viewer-chi.vercel.app/react-pdf-viewer/api/pdf-viewer-props.md)

---

## FullscreenMode reference

How fullscreen is presented: the browser Fullscreen API, a full-viewport overlay, or layout only while the parent presents it.

- `'controlled'`: layout-only; the parent decides how to present fullscreen.
- `'native'`: the browser Fullscreen API on the viewer root, falling back to `'overlay'`.
- `'overlay'`: a fixed, full-viewport layer with a focus trap; `Esc` closes it.

### Used by

- [Fullscreen](https://react-pdf-viewer-chi.vercel.app/react-pdf-viewer/fullscreen.md)

### Import

```ts
import type { FullscreenMode } from '@kingtech/react-pdf-viewer';
```

Signature: `type FullscreenMode = 'controlled' | 'native' | 'overlay'`

### Properties

| Name | Type | Default | Required | Description |
| --- | --- | --- | --- | --- |
| `controlled` | `'controlled'` | — | No | Layout only: the parent decides how to present fullscreen. |
| `native` | `'native'` | — | No | The browser Fullscreen API on the viewer root, falling back to `'overlay'`. |
| `overlay` | `'overlay'` | — | No | A fixed, full-viewport layer with a focus trap and scroll lock; `Esc` closes it. |

### Source

[packages/react-pdf-viewer/src/types.ts](https://github.com/kiralygyula92/react-pdf-viewer/blob/main/packages/react-pdf-viewer/src/types.ts#L35)


---

## PdfViewerProps reference

Props for `PdfViewer`. Every piece of state supports the value / defaultValue / onChange trio.

### Used by

- [Page navigation](https://react-pdf-viewer-chi.vercel.app/react-pdf-viewer/page-navigation.md)
- [Zoom](https://react-pdf-viewer-chi.vercel.app/react-pdf-viewer/zoom.md)
- [Rotation](https://react-pdf-viewer-chi.vercel.app/react-pdf-viewer/rotation.md)
- [Download](https://react-pdf-viewer-chi.vercel.app/react-pdf-viewer/download.md)
- [Print](https://react-pdf-viewer-chi.vercel.app/react-pdf-viewer/print.md)
- [Fit modes](https://react-pdf-viewer-chi.vercel.app/react-pdf-viewer/fit-modes.md)
- [Fullscreen](https://react-pdf-viewer-chi.vercel.app/react-pdf-viewer/fullscreen.md)
- [Continuous layout](https://react-pdf-viewer-chi.vercel.app/react-pdf-viewer/continuous-layout.md)
- [Thumbnails](https://react-pdf-viewer-chi.vercel.app/react-pdf-viewer/thumbnails.md)
- [Loading states](https://react-pdf-viewer-chi.vercel.app/react-pdf-viewer/loading-states.md)
- [Page number input](https://react-pdf-viewer-chi.vercel.app/react-pdf-viewer/page-number-input.md)
- [Links](https://react-pdf-viewer-chi.vercel.app/react-pdf-viewer/links.md)
- [Text layer](https://react-pdf-viewer-chi.vercel.app/react-pdf-viewer/text-layer.md)
- [Search](https://react-pdf-viewer-chi.vercel.app/react-pdf-viewer/search.md)
- [Password protection](https://react-pdf-viewer-chi.vercel.app/react-pdf-viewer/password-protection.md)
- [Rendering](https://react-pdf-viewer-chi.vercel.app/react-pdf-viewer/rendering.md)

### Import

```ts
import type { PdfViewerProps } from '@kingtech/react-pdf-viewer';
```

### Properties

| Name | Type | Default | Required | Description |
| --- | --- | --- | --- | --- |
| `source` | `PdfSource \| null` | — | Yes | The document: a URL string or `URL`, or `ArrayBuffer` / `Uint8Array` / `Blob` / `File`. `null`, `undefined` and `''` show the empty state. |
| `fileName` | `string` | `derived from the source` | No | Download file name. Default: a `File`’s name, the URL’s last `.pdf` segment, else `document.pdf`. |
| `page` | `number` | — | No | Controlled 1-based page. Out-of-range values are clamped and reported through `onPageChange`. |
| `defaultPage` | `number` | `1` | No | Initial page while uncontrolled, and the page every new document opens on. |
| `onPageChange` | `(page: number) => void` | — | No | Called whenever the page changes, controlled or not. |
| `scale` | `number` | — | No | Controlled scale: `1` = 100%, one PDF point per CSS pixel. |
| `defaultScale` | `number` | `1` | No | Initial scale while uncontrolled; also the reset-zoom target and the scale at which fitting applies. |
| `onScaleChange` | `(scale: number) => void` | — | No | Called whenever the scale changes. |
| `rotation` | `Rotation` | — | No | Controlled clockwise rotation, added to each page’s intrinsic rotation. |
| `defaultRotation` | `Rotation` | `0` | No | Initial rotation while uncontrolled. |
| `onRotationChange` | `(rotation: Rotation) => void` | — | No | Called whenever the rotation changes. |
| `fullscreen` | `boolean` | — | No | Controlled fullscreen state. Passing it selects `fullscreenMode="controlled"` unless a mode is set. |
| `defaultFullscreen` | `boolean` | `false` | No | Initial fullscreen state while uncontrolled. |
| `onFullscreenChange` | `(fullscreen: boolean) => void` | — | No | Called whenever fullscreen is entered or left. |
| `fullscreenMode` | `FullscreenMode` | `'controlled' when fullscreen is passed, else 'native'` | No | `controlled`: layout only, the parent presents fullscreen (e.g. in its own dialog). `native`: the browser Fullscreen API on the viewer root, falling back to `overlay`. `overlay`: a fixed full-viewport layer with a focus trap; `Esc` closes it. |
| `minScale` | `number` | `0.25` | No | Zoom floor (25%). |
| `maxScale` | `number` | `5` | No | Zoom ceiling (500%). |
| `scaleStep` | `number` | `0.05` | No | Increment of the zoom buttons and the `+` / `-` keys. |
| `zoomLevels` | `readonly number[]` | — | No | Preset ladder, e.g. `[0.5, 1, 1.5, 2, 4]`: the zoom buttons step between presets instead of by `scaleStep`. |
| `fitWidthAtDefaultScale` | `boolean` | `true` | No | At the default scale, shrink the page to the available width. |
| `fitMode` | `'page' \| 'none' \| 'width'` | `'none'` | No | At the default scale, fill the width (`width`) or fit the whole page (`page`). Zooming away shows the page at true size. |
| `password` | `string` | — | No | Password for encrypted documents. Changing it reloads the document. |
| `pdfjsOptions` | `PdfJsDocumentOptions` | — | No | Per-instance `getDocument` overrides such as `cMapUrl`, `standardFontDataUrl` or `verbosity`. Source-related options are managed by the viewer. |
| `toolbar` | `boolean \| ToolbarConfig` | `true` | No | `false` hides the toolbar; an object sets `position`, `actions` and `hiddenWhenCompact`. |
| `compactBreakpoint` | `number` | `960` | No | Viewport width (px) below which the compact layout applies: less padding, and `hiddenWhenCompact` actions hidden outside fullscreen. |
| `keyboardShortcuts` | `boolean` | `true` | No | Keyboard shortcuts while focus is inside the viewer. |
| `printMode` | `'render' \| 'open-url'` | `'render'` | No | `render` prints through a hidden iframe, with progress and Cancel; `open-url` opens the PDF in a new tab. |
| `maxCanvasPixels` | `number` | `16777216` | No | Canvas pixel budget per page (4096 × 4096). Above it, resolution degrades gracefully instead of failing. |
| `labels` | `Partial<PdfViewerLabels>` | `English (defaultLabels)` | No | Overrides for any visible string or accessible name. Keep the object stable (e.g. at module scope). |
| `locale` | `string` | `the browser locale` | No | BCP 47 locale for number formatting, e.g. `hu-HU`. |
| `layout` | `'single' \| 'continuous'` | `'single'` | No | One page at a time or vertical scrolling through all pages. Only the visible pages ±1 are rendered; the page indicator follows the scroll position. |
| `textLayer` | `boolean` | `false` | No | Selectable, copyable text that assistive technology can read. |
| `annotationLayer` | `boolean` | `false` | No | Clickable links: internal links navigate, external links open in a new tab with `rel="noopener noreferrer"`. |
| `pageInput` | `boolean` | `false` | No | Editable page number in the toolbar. |
| `zoomReset` | `boolean` | `false` | No | The zoom label becomes a button that resets zoom. |
| `wheelZoom` | `boolean` | `false` | No | `Ctrl` / `⌘` + wheel and trackpad pinch zoom, anchored at the pointer. |
| `passwordPrompt` | `boolean` | `false` | No | Ask for the password of encrypted documents instead of reporting `PASSWORD_REQUIRED`. |
| `renderPasswordPrompt` | `(context: { incorrect: boolean; submit: (password: string) => void }) => ReactNode` | — | No | Replaces the built-in password form (with `passwordPrompt`). |
| `thumbnails` | `boolean` | `false` | No | Lazily rendered page thumbnails sidebar, hidden in compact, non-fullscreen mode. |
| `search` | `boolean` | `false` | No | Find bar with highlighting (implies `textLayer`). `Ctrl` / `⌘` + `F` focuses it, `Enter` / `Shift` + `Enter` step through matches, `Esc` clears. |
| `renderLoading` | `() => ReactNode` | — | No | Replaces the loading view. |
| `renderError` | `(error: PdfViewerError, actions: { retry: () => void }) => ReactNode` | — | No | Replaces the document and page error views. |
| `renderToolbar` | `(api: PdfViewerApi) => ReactNode` | — | No | Replaces the toolbar. Render `&lt;PdfToolbar api={api} /&gt;` inside to reuse parts. |
| `renderEmpty` | `() => ReactNode` | — | No | Replaces the view shown without a source. |
| `onDocumentLoad` | `(info: { numPages: number; fingerprint: string }) => void` | — | No | A document finished loading. |
| `onPageRender` | `(info: PageRenderInfo) => void` | — | No | A page render completed. |
| `onError` | `(error: PdfViewerError) => void` | — | No | Every failure except aborted loads, canceled renders and HTTP errors handled by `onHttpError`. |
| `onDownload` | `(context: { fileName: string; data: Uint8Array }) => false \| void` | — | No | Before saving; `data` holds the already-loaded bytes. Return `false` to handle the download yourself. |
| `onPrint` | `() => false \| void` | — | No | Before printing. Return `false` to handle printing yourself. |
| `className` | `string` | — | No | Added to the root (`.rpv-root`). `rpv-theme-dark` and `rpv-theme-auto` select the dark presets. |
| `style` | `CSSProperties` | — | No | Inline styles on the root, e.g. CSS variables. |
| `id` | `string` | — | No | Id of the root element. |
| `aria-label` | `string` | `labels.viewer` | No | Accessible name of the viewer region. |
| `requestInit` | `RequestInit` | — | No | Extra `fetch` options for URL sources: headers, `credentials`, `mode`, … |
| `fetcher` | `(url: string, init: RequestInit) => Promise<Response>` | — | No | Replaces `fetch` entirely, e.g. with an authenticated HTTP client. |
| `onHttpError` | `(response: Response) => boolean \| void \| Promise<boolean \| void>` | — | No | Called for non-2xx responses. Return `true` when handled (e.g. after redirecting to sign-in): the viewer shows its empty state and does not call `onError`. |
| `getHttpErrorMessage` | `(response: Response) => Promise<string>` | — | No | Builds the `HTTP_ERROR` message. Return `undefined` for the default: an RFC 7807 `detail`, then `title`, then a JSON string body, then `Failed to fetch PDF: {status} {statusText}`. |

### Source

[packages/react-pdf-viewer/src/types.ts](https://github.com/kiralygyula92/react-pdf-viewer/blob/main/packages/react-pdf-viewer/src/types.ts#L190)

