EmbedPDF

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, and with dark for dark only:

{
  theme: {
    accent: '#0f6e56',
    tokens: { surface: '#fbfaf7', radius: '2px' },
    dark: { surface: '#16201c' },
  },
}
TokenWhat it colorsLightDark
accentPressed buttons, the active tab, links, focus rings, and every part on the pages that has no color of its own#3b82f6#60a5fa
backgroundBehind the bars and panels#f3f4f6#111827
surfaceBars and panels#ffffff#1f2937
surface-raisedMenus, sheets, dialogs and floating bars#ffffff#1f2937
textLabels and text#111827#f9fafb
text-mutedSecondary text, such as a page count#6b7280#9ca3af
borderLines between bars, panels and groups#d1d5db#4b5563
hoverA button under the pointer#f3f4f6#374151
canvasBehind the pages#f3f4f6#0d1117
radiusThe corners of buttons, menus and panels6px6px
fontEvery word the viewer writesyour system’s fontyour system’s font

The pages themselves have their 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;
}
PartWhat it is
toolbarA bar
toolbar-button, toolbar-button-activeA button in a bar, and a pressed one
mode-tab, mode-tab-activeA mode tab, and the selected one
tab, tab-activeA document tab, and the open one
menu, menu-item, menu-item-activeA menu, a row, and the row of the current choice
panel, panel-headerA panel, and its header

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.

Was this page helpful?

Your feedback goes directly to the documentation team.