Theming
Give the viewer your brand color, and every part follows it: pressed buttons, the active tab, focus rings, the text selection, the handles of a selected annotation.
{
theme: { preference: 'system', accent: '#7c3aed' },
}preference is 'light', 'dark' or 'system', which follows the user’s setting and switches
when they change it. theme: 'dark' is short for theme: { preference: 'dark' }. theme follows
its prop, so a theme switch in your app switches the viewer too.
Every color#
Change any of them with tokens for both light and dark, with light for light only, and with
dark for dark only:
{
theme: {
accent: '#0f6e56',
tokens: { radius: '2px' },
light: { surface: '#fbfaf7' },
dark: { surface: '#16201c', 'page-shadow': 'none' },
},
}When more than one sets a token, light or dark wins in its mode, then tokens, then accent.
A CSS variable wins over all of them: see From CSS.
This one gives each color its light value in light and its dark value in dark, and a switch in
the app sets preference:
Loading live preview…
<link rel="stylesheet" href="./colors.css" />
<div class="app" id="app">
<header class="bar">
<label>
<input type="checkbox" id="dark" />
Dark
</label>
</header>
<embedpdf-viewer id="viewer" class="viewer"></embedpdf-viewer>
</div>
<script type="module">
import 'https://cdn.jsdelivr.net/npm/@embedpdf/viewer@3/dist/embedpdf.js';
const welcome = '/pdfs/welcome.pdf';
// What both modes share, then the colors of each.
const brand = {
accent: '#0f6e56',
tokens: { radius: '2px' },
light: { surface: '#fbfaf7', canvas: '#ece8df' },
dark: {
accent: '#4fbf98',
surface: '#16201c',
'surface-raised': '#1d2a25',
canvas: '#0c1210',
hover: '#24332d',
},
};
const app = document.getElementById('app');
const viewer = document.getElementById('viewer');
const dark = document.getElementById('dark');
// Your app and the viewer, light or dark as the switch says.
const show = () => {
app.classList.toggle('dark', dark.checked);
viewer.theme = { ...brand, preference: dark.checked ? 'dark' : 'light' };
};
viewer.config = { src: welcome };
show();
dark.addEventListener('change', show);
</script>Try it: tick Dark above the viewer, then open the menu at the top left: the bars, the menus and the space behind the pages all take your dark colors. Untick it to go back.
| Token | What it colors | Light | Dark |
|---|---|---|---|
accent | Pressed buttons, primary buttons, the active tab, links, focus rings, and every part on the pages that has no color of its own | #3b82f6 | #60a5fa |
background | Behind the bars and panels | #f3f4f6 | #111827 |
surface | Bars and panels | #ffffff | #1f2937 |
surface-raised | Menus, sheets, dialogs and floating bars | #ffffff | #1f2937 |
text | Labels and text | #111827 | #f9fafb |
text-muted | Secondary text, such as a page count | #6b7280 | #9ca3af |
border | Lines between bars, panels and groups | #d1d5db | #4b5563 |
hover | A button under the pointer | #f3f4f6 | #374151 |
canvas | Behind the pages | #f3f4f6 | #0d1117 |
page-background | A page before its picture arrives | #ffffff | #ffffff |
page-shadow | The shadow under each page; none for none | 0 6px 18px rgb(0 0 0 / 0.18) | 0 6px 18px rgb(0 0 0 / 0.18) |
tooltip | Behind a tooltip’s words | text’s color | text’s color |
tooltip-text | A tooltip’s words | surface’s color | surface’s color |
radius | The corners of buttons, menus, panels, tooltips and the bars floating over the pages | 6px | 6px |
font | Every word the viewer writes, its tooltips’ too | your system’s font | your system’s font |
What’s drawn on the pages has its own colors: the text selection, search matches, the handles of
a selected annotation, form fields. Every one follows accent until you set it, and every one is
listed on Colors & theming in the headless docs, as a
plugin setting and a CSS variable. Both work in the viewer.
From CSS#
Every token is also a CSS variable: --epdf- and its name. Set it on the viewer or on any element
around it. A CSS variable wins over the config:
embedpdf-viewer {
--epdf-accent: #e91e63;
--epdf-radius: 0;
}
[data-theme='dark'] embedpdf-viewer {
--epdf-surface: #101418;
}Use it to keep colors in your stylesheet, to follow a theme class your app already switches, or to give two viewers on one page their own look.
Restyle a part#
The main parts have a name you can reach with ::part(), for what tokens don’t cover:
embedpdf-viewer::part(toolbar-button) {
border-radius: 999px;
}
embedpdf-viewer::part(mode-tab-active) {
font-weight: 600;
}
embedpdf-viewer::part(toolbar-review) {
background: #fef3c7;
}| Part | What it is |
|---|---|
toolbar, toolbar-<id> | A bar, and the bar with that id: toolbar-main, toolbar-pager, or toolbar-review for a bar you added as review |
toolbar-button, toolbar-button-active | A button in a bar, and a pressed one |
toolbar-button-primary | A primary button |
tooltip | A tooltip |
mode-tab, mode-tab-active | A mode tab, and the selected one |
tab, tab-active | A document tab, and the open one |
menu, menu-item, menu-item-active | A menu, a row, and the row of the current choice |
panel, panel-header | A panel, and its header |
page-loading, page-error | The spinner on a page whose picture is on its way, and the message on one that couldn’t load |
Part names are kept between minor versions, like every other id.
In your own components#
Your own components inherit the viewer’s font and text color, and can use every token as a CSS variable:
.version-picker {
background: var(--epdf-surface);
color: var(--epdf-text);
border: 1px solid var(--epdf-border);
border-radius: var(--epdf-radius);
}Good to know#
Your page’s CSS stays out#
The viewer draws inside its own shadow DOM, so your page’s styles don’t change it and its styles
don’t change your page. A global button { … } rule, a CSS reset, or html { font-size: 62.5% }
leaves the viewer as it is. What does reach it is what you aim at it: the CSS variables above and
::part().
Tailwind#
Set a variable with an arbitrary property on an element around the viewer:
class="[--epdf-accent:var(--color-violet-600)]".
Colors saved in the PDF#
An annotation’s color, a redaction’s fill and a form field’s look belong to the document, not to the theme: they look the same in every app that opens the file. Their defaults are the tools’ settings: see Annotations.
Your feedback goes directly to the documentation team.