Fast, lightweight PDF viewer component for Vue 3 and Nuxt 4 powered by pdf.js. Built for zero-config setup, strong performance on large PDFs, and clean TypeScript support.
Use this package when you need a Vue PDF viewer with toolbar controls, virtualization, zoom, pagination, download, print, and Nuxt compatibility.
- Virtualized page rendering
- Zoom in/out and fit-to-width
- Pagination controls
- Download and print
- Fullscreen toggle
- Polished compact toolbar and status UI
- Light and dark mode support
- TypeScript-first API
| Package Manager | Command |
|---|---|
| pnpm (preferred) | pnpm add vue-pdf-viewer-core pdfjs-dist |
| npm | npm i vue-pdf-viewer-core pdfjs-dist |
| yarn | yarn add vue-pdf-viewer-core pdfjs-dist |
| bun | bun add vue-pdf-viewer-core pdfjs-dist |
<script setup lang="ts">
import { PdfViewer } from "vue-pdf-viewer-core";
import "vue-pdf-viewer-core/style.css";
const pdfUrl = "https://example.com/my.pdf";
</script>
<template>
<PdfViewer :src="pdfUrl" />
</template>Recommended for Nuxt: enable the Nuxt module so component registration and base CSS are handled automatically.
- Add the module:
// nuxt.config.ts
export default defineNuxtConfig({
modules: ["vue-pdf-viewer-core/nuxt"],
});- Use the globally registered component:
<script setup lang="ts">
const pdfUrl = "https://example.com/my.pdf";
</script>
<template>
<PdfViewer :src="pdfUrl" />
</template>Alternative (without Nuxt module): direct component import and manual CSS import.
<script setup lang="ts">
import { PdfViewer as CorePdfViewer } from "vue-pdf-viewer-core";
import "vue-pdf-viewer-core/style.css";
const pdfUrl = "https://example.com/my.pdf";
</script>
<template>
<CorePdfViewer :src="pdfUrl" />
</template>fitToWidth, showToolbar, withCredentials, and theme already have defaults in PdfViewer, so you only need to pass them when overriding behavior.
If you wrap the viewer inside a Nuxt layer component, prefer forwarding useAttrs() (instead of re-declaring all props) so core defaults stay intact:
<script setup lang="ts">
import { useAttrs } from "vue";
import type { PdfViewerProps } from "vue-pdf-viewer-core";
const attrs = useAttrs() as Partial<PdfViewerProps>;
</script>
<template>
<PdfViewer v-bind="attrs" />
</template>- Works out of the box in Vue 3 and Nuxt 4.
- Uses pdf.js with a built-in worker path (no manual worker wiring needed).
- Keeps rendering fast on large documents with virtual windowing.
- Ships typed components for TypeScript projects.
PdfViewer props (defaults in parentheses):
src(required)withCredentials(false)initialPage(1)initialScale(1)fitToWidth(true)minScale(0.5)maxScale(5)zoomStep(0.1)maxConcurrentRenders(2)virtualWindowSize(2)showToolbar(true)theme("auto") accepts"auto" | "light" | "dark"
page-change(page number)load-error(error)action-error(error)
Set theme mode directly via prop:
<PdfViewer :src="pdfUrl" theme="dark" />Use theme="auto" (default) to follow your app-level .dark class, or override CSS variables to match your app theme:
:root {
--lpv-bg: #f6f6f6;
--lpv-panel: #e9e9e9;
--lpv-border: #d1d1d1;
--lpv-text: #1f1f1f;
--lpv-toolbar-text: #1f1f1f;
--lpv-icon-color: #1f1f1f;
--lpv-error: #b42318;
--lpv-surface-radius: 0.45rem;
--lpv-inline-gutter: 0.45rem;
--lpv-toolbar-top-gap: 0.25rem;
--lpv-toolbar-sticky-top: 0.5rem;
--lpv-tooltip-bg: #fff;
--lpv-tooltip-text: #1f1f1f;
--lpv-tooltip-border: color-mix(
in oklab,
var(--lpv-border) 65%,
transparent 35%
);
--lpv-tooltip-shadow: 0 0.28rem 0.72rem rgb(0 0 0 / 10%);
}The default UI is intentionally compact and refined; CSS variables let you re-skin colors and contrast to match your brand.
- Vite playground:
playground/ - Nuxt playground:
playground-nuxt/
npm -C playground install
npm -C playground run dev
npm -C playground-nuxt install
npm -C playground-nuxt run dev- Vite playground: https://stirstudios.github.io/vue-pdf-viewer-core/playground/
- Nuxt playground: https://stirstudios.github.io/vue-pdf-viewer-core/nuxt/
- If you see
window is not defined, render the viewer in<ClientOnly>. - If styles are missing, ensure
import 'vue-pdf-viewer-core/style.css'is loaded. - If a Nuxt layer wrapper uses
defineProps()and forwardsv-bind="props", boolean props can be coerced and override core defaults. PreferuseAttrs()pass-through wrappers when you want PdfViewer defaults preserved. - If PDFs require auth cookies, pass
:with-credentials="true".
This project targets practical WCAG 2.1/2.2 AA conformance for core viewer and toolbar flows.
Implemented accessibility hardening includes:
-
Semantic roles and accessible names for core toolbar and viewer controls
-
Keyboard interaction support for navigation/actions, including menu
Escapeclose + focus return -
Live announcements for loading, errors, page changes, and zoom updates
-
Focus-visible states for interactive controls
-
Theme-aware UI surfaces (toolbar, menu, tooltip) in light/dark/auto modes
-
Automated checks:
npm run test:a11y(axe in Vitest) and CI regression step. -
Contrast regression checks:
npm run test:contrastfor core light/dark token pairs. -
Manual checks: keyboard-only and screen-reader matrices in
docs/accessibility/. -
Theme checks: contrast audit notes for light/dark/auto themes in
docs/accessibility/contrast-audit.md. -
Scope:
PdfViewer,PdfToolbar, and default styles insrc/style.css.
Known limitations:
- Canvas-rendered PDF page content is not semantically exposed to assistive tech by default.
- This is a best-effort WCAG AA implementation, not a legal certification.
- Formal certification/legal conformance claims require external third-party audit.
- Contributing:
CONTRIBUTING.md - Code of Conduct:
CODE_OF_CONDUCT.md - Security:
SECURITY.md - Accessibility Baseline Report:
docs/accessibility/baseline-report.md - Keyboard Matrix:
docs/accessibility/keyboard-matrix.md - Screen Reader Matrix:
docs/accessibility/screen-reader-matrix.md - Contrast Audit:
docs/accessibility/contrast-audit.md
MIT