Skip to content

Theming

The Reast Engine is themed through CSS custom properties, all prefixed --re-. Override them on the <reast-engine> element or any ancestor — the values inherit through the Shadow DOM boundary.

Two style sheets

The engine ships two adopted stylesheets:

  • playerStyles — structural styles, adopted by every element. Its colour and typography defaults lean on inherit, currentColor and transparent, so an unstyled embed adopts the host page's look instead of imposing one. A bare <reast-engine> inside your app inherits your font, colour and background.
  • standaloneStyles — the opinionated reading palette (colours, fonts, dark-mode and high-contrast remaps, and the default lightbox overlay). It is adopted only by the standalone CDN build, on top of playerStyles.

So the CDN snippet looks designed out of the box, while an embedded element looks like part of your site until you theme it.

Custom properties

"Embedded" is what an unthemed embed gets from playerStyles; "Standalone" is what standaloneStyles assigns in the CDN build.

Layout

PropertyDefaultDescription
--re-max-width42remMaximum content width
--re-padding1.5remInner padding

Colours

PropertyEmbeddedStandalone (light)Description
--re-color-bgtransparent#faf9f6Background
--re-color-textinherit#1f1f2eBody text
--re-color-headinginherits textinherits textHeading colour
--re-color-text-mutedinherit#5c5c6eMuted/secondary text
--re-color-bordercurrentColor#d4d4d8Borders
--re-color-accentcurrentColor#5b4fc7Accent / links
--re-color-accent-hovercurrentColor#4a3fb0Accent hover
--re-color-code-bgcurrentColor tintrgba(0,0,0,0.06)Code background
--re-color-danger#dc2626#dc2626Error colour
--re-color-highlighttranslucent yellowtranslucent yellowHighlight-mark background
--re-color-choice-bgtransparentrgba(91,79,199,0.06)Choice background
--re-color-choice-bordercurrentColor tintrgba(91,79,199,0.2)Choice border
--re-color-choice-bg-hovercurrentColor tintrgba(91,79,199,0.12)Choice hover background

Typography

PropertyEmbeddedStandaloneDescription
--re-font-bodyinherit'Literata', Georgia, serifBody font stack
--re-font-headinginherits bodyinherits bodyHeading font stack
--re-font-monomonospace'Fira Code', monospaceMonospace font
--re-font-sizeinheritclamp(1.0625rem, …, 1.25rem)Base font size
--re-line-heightinherit1.7Body line height
--re-h1-size--re-h5-size2em1emsameHeading sizes

Spacing & shape

PropertyDefaultDescription
--re-paragraph-spacing1emSpace between paragraphs
--re-heading-margin1.5em 0.5emHeading block margin
--re-hr-margin2emHorizontal-rule margin
--re-choice-gap0.5emGap between choices
--re-choice-radius6pxChoice border radius
--re-choice-padding0.75em 1emChoice inner padding
--re-media-radius6pxMedia border radius
--re-transition-speed0.2sGlobal transition speed (0s under reduced-motion)

Standalone-only remaps

The CDN build's standaloneStyles also defines --re-dark-* values applied under @media (prefers-color-scheme: dark) and --re-hc-* values applied under @media (prefers-contrast: more). An embedded element does not ship these — a host that wants dark mode sets --re-color-* itself (typically inheriting from its own theme), which is usually what you want, since the embed already adopts the host's colours.

Example: dark embed

Because the embedded defaults inherit, the simplest dark theme is to let the element inherit a dark host, or set a few properties:

css
reast-engine {
  --re-color-bg: #1a1a2e;
  --re-color-text: #e0e0e0;
  --re-color-accent: #a78bfa;
  --re-color-accent-hover: #8b6ff0;
  --re-color-border: #374151;
}

Example: minimal reader

css
reast-engine {
  --re-font-body: 'Literata', serif;
  --re-font-size: 1.25rem;
  --re-line-height: 1.8;
  --re-max-width: 55ch;
  --re-paragraph-spacing: 2em;
}

Escape hatch: extraStyleSheets

For rules that CSS custom properties cannot express, push a CSSStyleSheet onto ReastEngine.extraStyleSheets before constructing any element — it is adopted into every element's shadow root after playerStyles. Already-created instances are not retrofitted. (This is exactly how the standalone build adds standaloneStyles.)

ts
import { ReastEngine, registerEngine } from '@reast/engine/player';

const sheet = new CSSStyleSheet();
sheet.replaceSync(`.re-choice { text-transform: uppercase; }`);
ReastEngine.extraStyleSheets.push(sheet);

registerEngine();

Shadow DOM boundary

The player renders inside Shadow DOM, so host page styles do not leak in and story styles do not leak out. Custom properties and extraStyleSheets are the supported ways across the boundary; the element also exposes part attributes (identity, identity-title, identity-authors) for ::part() styling.