Theming

Inherit the portal's colors, light/dark mode, and visible viewport automatically.

A portal block should look like it belongs in the portal that hosts it. The SDK makes that automatic: the portal's theme is delivered across the bridge and applied to your document, then kept in sync as the user switches themes, with no work required beyond initialize().

How it works

The portal can't reach into a cross-origin iframe to style it, so it sends theme data through the bridge as a string of CSS custom properties. During initialize() the SDK:

  1. Injects the portal's cssVariables into a <style id="spark-portal-theme"> in your <head>.
  2. Applies the light / dark class to <html>.
  3. Subscribes to theme-update and viewport-update messages so later changes apply live and the cached session stays current.

If you build with the Spark UI component library, those CSS variables are exactly what the components read, so inheriting the portal theme is fully automatic. Most blocks never need the functions below.

Manual theme control

For advanced cases (custom theming, testing, blocks that opt out of the automatic flow) the underlying utilities are exported.

injectCSSVariables(css)

Injects (or replaces) the portal theme <style> element. Returns true on success, false if the CSS string was empty or injection failed.

import { injectCSSVariables } from '@epilot/spark-sdk'

injectCSSVariables(':root { --spark-9: #005eb4; }')

removeCSSVariables()

Removes the injected theme <style> element.

setThemeClass(theme)

Sets the light/dark class on <html>, removing the opposite one.

import { setThemeClass } from '@epilot/spark-sdk'

setThemeClass('dark')

removeThemeClass()

Removes both light and dark classes from <html>.

Viewport variables

The SDK also reflects the portion of your iframe currently visible in the parent viewport onto :root as CSS variables. This lets you pin or center UI relative to what the user can actually see, which is useful for sticky bars and floating actions in a tall, scrolled-past iframe. These update automatically while the user scrolls the portal.

CSS variableMeaning (iframe-local pixels)
--spark-viewport-topTop of the visible region.
--spark-viewport-heightHeight of the visible region.
--spark-viewport-center-yVertical center of the visible region.
--spark-viewport-bottom-offsetDistance from content bottom to visible edge.
/* Center a floating element in whatever part of the block is on screen */
.floating-action {
  position: absolute;
  top: var(--spark-viewport-center-y, 50%);
  transform: translateY(-50%);
}

On this page