This HTML page is not optimized for LLM or AI agent consumption. Fetch the Markdown version instead: /guides/web/user-interface/theming/dark-theme.md — it contains the complete documentation content in clean, structured Markdown without any CSS, JavaScript, or navigation noise. JavaScript PDF viewer dark mode | Nutrient SDK

With Nutrient Web SDK, it’s possible to change the interface to dark mode programmatically or based on device information.

The NutrientViewer.Configuration#theme property accepts one of six values:

The default value is NutrientViewer.Theme.LIGHT, which is the light theme.

You can set your preferred theme in the configuration object passed to NutrientViewer.load (try it in the Playground(opens in a new tab)).

Applying dark theme

Here’s a complete example of applying the dark theme:

import NutrientViewer from "@nutrient-sdk/viewer";
// Get the container element where the viewer will be mounted.
const container = document.getElementById("nutrient-container");
NutrientViewer.load({
container,
document: "document.pdf",
theme: NutrientViewer.Theme.DARK,
}).catch((error) => {
console.error("Failed to load viewer:", error);
});

Automatic theme based on system preference

NutrientViewer.Theme.AUTO will automatically choose the theme based on the user preferences and the prefers-color-scheme media query, which isn’t available in every browser. You can check the current browser support for the prefers-color-scheme media query here(opens in a new tab).

If the system color scheme changes after the viewer has loaded, only part of the interface follows. Surfaces driven by the design tokens update immediately, but the theme stylesheet is chosen once at load, so the surfaces it styles — the annotation toolbar, sidebar headers, and some dialog chrome — stay on the theme resolved at load. Reload the viewer to apply the change everywhere.

import NutrientViewer from "@nutrient-sdk/viewer";
const container = document.getElementById("nutrient-container");
NutrientViewer.load({
container,
document: "document.pdf",
theme: NutrientViewer.Theme.AUTO,
}).catch((error) => {
console.error("Failed to load viewer:", error);
});

High contrast themes

For improved accessibility, you can use the high contrast themes:

import NutrientViewer from "@nutrient-sdk/viewer";
const container = document.getElementById("nutrient-container");
// High contrast dark theme.
NutrientViewer.load({
container,
document: "document.pdf",
theme: NutrientViewer.Theme.HIGH_CONTRAST_DARK,
}).catch((error) => {
console.error("Failed to load viewer:", error);
});

Changing theme at runtime

There’s no supported API for changing the theme of an existing viewer instance. ViewState has no theme property, so calling setViewState with one changes nothing and reports no error.

To switch the theme, unload the instance and load a new one with a different theme:

import NutrientViewer from "@nutrient-sdk/viewer";
const container = document.getElementById("nutrient-container");
const toggle = document.getElementById("dark-mode-toggle");
let instance = null;
let currentTheme = NutrientViewer.Theme.LIGHT;
async function loadWithTheme(theme) {
// Loading is asynchronous, so block a second switch until this one settles.
toggle.disabled = true;
try {
// `load()` throws if the container already holds an instance; `unload()` is a no-op when it doesn't.
const initialViewState = instance?.viewState;
NutrientViewer.unload(container);
instance = await NutrientViewer.load({
container,
document: "document.pdf",
initialViewState,
theme,
});
currentTheme = theme;
} catch (error) {
console.error("Failed to load viewer:", error);
} finally {
toggle.disabled = false;
}
}
loadWithTheme(currentTheme);
toggle.addEventListener("click", () => {
loadWithTheme(
currentTheme === NutrientViewer.Theme.LIGHT
? NutrientViewer.Theme.DARK
: NutrientViewer.Theme.LIGHT
);
});

The reload creates a new instance, so the sample hands the view state across as initialViewState. Annotations and document edits aren’t carried over that way.

With Document Engine, save them with instance.save() before unloading. In Standalone, save() writes to the local backend rather than back to the document URL, so export the document with instance.exportPDF() and pass the resulting ArrayBuffer as document in the new configuration.