API Reference
Complete documentation for the <bg-wc> web component.
Install
npm
Then import the element. The component self-registers as
<bg-wc> on import.
From source / CDN
Or vendor the src/ directory and reference it directly —
it ships as plain ES modules with no build step.
Quick start
Drop the element on any page that defines the usual VB color tokens
(--color-primary, --color-accent, …).
The component reads them at frame time.
Nothing required beyond the preset attribute. The
fallback slot shows when prefers-reduced-motion: reduce
is active and the chosen preset has no staticFrame().
data-background behavior
For pages that don't want to introduce a new custom element into
their markup, import the optional data-background binder. It
scans for elements with a data-background attribute and
injects a <bg-wc> behind that element's content
via z-index: -1 inside an isolated stacking context.
The namespace is distinct from VB's data-effect, so
the two can coexist on the same element.
Attribute mapping
data-background is the preset name. Any other key starting with
data-background- maps to the corresponding bg-wc attribute — or, for
color overrides, the corresponding --bg-wc-color-* custom
property:
| data-background-* | Maps to |
|---|---|
data-background | The preset attribute. Required. |
data-background-intensity | intensity attribute |
data-background-speed | speed |
data-background-density | density |
data-background-seed | seed |
data-background-palette | palette |
data-background-quality | quality |
data-background-fit | fit |
data-background-motion | motion |
data-background-paused | paused |
data-background-pixel-ratio | pixel-ratio |
data-background-color-1 | --bg-wc-color-1 CSS var |
data-background-color-2 | --bg-wc-color-2 |
data-background-color-3 | --bg-wc-color-3 |
data-background-color-bg | --bg-wc-color-bg |
data-background-color-fg | --bg-wc-color-fg |
data-background-skip | Presence skips binding (escape hatch). |
New elements added to the page after first paint are auto-bound via
a MutationObserver. To bind manually after disabling that
observer (or in an SSR context), call
bindDataBackgrounds(root) after import.
Attributes
All attributes are observed; changes after first render are applied
without re-init for cheap params, and trigger a renderer swap for
preset.
| Attribute | Type / values | Default | Notes |
|---|---|---|---|
preset | preset name | — | Required. See the catalog. |
palette | "theme" | "rainbow" | "mono" | "theme" | Honored by particles most strongly. |
intensity | 0..1 | 0.5 | Preset-specific "how dramatic" knob. |
speed | 0..5 | 1 | Time multiplier. 0 freezes. |
density | 0..1 | 0.5 | Particle count / shader detail. |
seed | integer | 0 | Deterministic randomness. Useful for screenshots. |
paused | boolean | unset | Pauses the RAF loop without unmounting. |
pixel-ratio | number | min(devicePixelRatio, 2) | Lower it for cheaper rendering on big screens. |
quality | "low" | "med" | "high" | "med" | Renderer-level hint. |
fit | "cover" | "contain" | "stretch" | "cover" | How the surface sizes inside the host. |
motion | "auto" | "reduce" | "force" | "auto" | auto honors prefers-reduced-motion. |
text | string | — | Payload for text presets (crawl / marquee / sinescroll / cascade). Lines split on |. Read fresh each frame. |
mode | string | — | Preset-specific variant selector. mosaic: isometric, flat, sparse, stacked; doodles: family names; fly-through: space-delimited motion×profile×path×unit; explode: radial | cube. Changing it rebuilds css3d scenes. girih: 8fold/12fold/6fold; atomic: mixed/boomerangs/starbursts/harlequin; op-art: riley/cafewall/moire/drift. |
use-theme | boolean | unset | Used by system7; presence enables theme-token coloring instead of hard black/white. |
Properties & methods
| Member | Type | Behavior |
|---|---|---|
.preset | string | Reflects the preset attribute. |
.paused | boolean | Reflects the paused attribute. |
.pause() | () => void | Pauses the render loop. |
.resume() | () => void | Resumes the render loop. |
.snapshot() | () => Promise<Blob> | Returns a PNG snapshot of the current frame. |
.ready | Promise<void> | Resolves when the active preset's first frame has rendered. |
Events
| Event | Detail | When |
|---|---|---|
bg-wc:ready | { preset, renderer } | First frame rendered. |
bg-wc:preset-changed | { from, to } | After a successful preset swap. |
bg-wc:error | { phase, error } | Compile, load, or runtime error. Element transitions to the fallback slot. |
bg-wc:visibility | { visible: boolean } | IntersectionObserver gate flipped. |
CSS custom properties
Tokens are read once per frame via getComputedStyle() —
theme switches reflect within one RAF tick without re-init.
Tokens the component reads
| Token | Used for | Fallback |
|---|---|---|
--color-background | Canvas backdrop / clear color | transparent |
--color-foreground | Default particle / line color | #1a1a1a |
--color-primary | Primary tint in shaders | #3b82f6 |
--color-accent | Accent tint | #ec4899 |
--color-info | Tertiary tint (mesh-gradient, aurora, …) | #10b981 |
--color-success | Confetti palette | #22c55e |
--color-warning | Confetti palette | #f59e0b |
--color-error | Confetti palette | #ef4444 |
Component-namespaced overrides
For when you want to feed a specific value without changing the global theme. Each one wins over the corresponding semantic token for that instance:
| Override | Beats |
|---|---|
--bg-wc-color-1 | --color-primary |
--bg-wc-color-2 | --color-accent |
--bg-wc-color-3 | --color-info |
--bg-wc-color-bg | --color-background |
--bg-wc-color-fg | --color-foreground |
--bg-wc-speed | speed attribute |
--bg-wc-density | density |
--bg-wc-intensity | intensity |
--bg-wc-pixel-ratio | pixel-ratio |
--bg-wc-z-index | Internal canvas stacking |
Shadow parts
The internal <canvas> is exposed as part="canvas":
Preset catalog
Each preset is its own dynamic import — loaded once on first use and cached. The kernel ships only the element class, the RAF loop, the renderer wrappers, and the token resolver.
WebGL shader presets
| Name | Visual | Tokens used |
|---|---|---|
dither | Animated halftone between two colors | primary, accent |
noise | Drifting fractal noise, two-color tint | foreground, background |
mesh-gradient | Stripe-style soft blob hero | primary, accent, info, background |
warp | Displacement-warped grid | primary, background |
waves | Four sine-displaced color bands | primary, accent, info, background |
lava | Metaball lava lamp | primary, accent, background |
plasma | Demoscene plasma, sum of sines | primary, accent, info |
aurora | Vertical curtain noise + baseline ribbon | primary, accent, info, background |
tunnel | Infinite polar zoom with ring banding | primary, accent, background |
caustics | Warped sin/cos fields for bright veins | primary, accent, background |
glitch | RGB-shift datamosh with per-row displacement | primary, accent, background |
rainbow | Flowing spectral hue sweep (owns its palette) | — (not theme-tinted) |
halftone | Rotated dot-grid halftone over an animated tone | primary, background |
kaleidoscope | Mirrored angular folds with a rotating pattern | primary, accent, info |
vhs | 80s analog video: wobble, chroma bleed, tracking noise | primary, accent, background |
synthwave | Outrun neon perspective grid + banded sun | primary, accent, info, background |
crt | CRT tube: barrel curve, scanlines, RGB phosphor mask | primary, accent, background |
gameboy | 4-tone handheld with ordered dither + pixelation | primary, background |
copperbars | Amiga demoscene metallic copper bars | primary, accent, info, background |
topology | Animated topographic contour lines | primary, accent, background |
cells | Animated Voronoi cells with darkened borders | primary, accent, background |
shine | Diagonal sheen sweep over a quiet gradient | primary, accent, background |
conic | Rotating angular gradient (spotlight border / loader) | primary, accent, info, background |
grain | Film-grain overlay; transparent, blend over content | — (monochrome speckle) |
trench | Death Star trench run: square perspective corridor | primary, accent, background |
marble | Domain-warped marble veins (mallsoft / luxe) | primary, accent, background |
benday | Pop-art Ben-Day dots over flat color blocks | primary, accent, info |
comic | Pop-art radial action burst + shock rings | primary, accent, info |
deco | Art-deco sunburst rays (Nagel / Gatsby) | primary, accent, info, background |
bliss | Windows-XP hills, sky, drifting clouds | primary, info, background |
Vector / arcade presets (Canvas2D)
Glowing phosphor lines on a dark field — the Vectrex / arcade-vector look.
| Name | Visual | Tokens used |
|---|---|---|
asteroids | Drifting, rotating wireframe rocks | primary, background |
wireframe | Rotating wireframe globe + equatorial trench | primary, accent, background |
spirograph | Animated hypotrochoid rosettes | primary, accent, info, background |
incoming | Wireframe ships warping toward a turret crosshair | primary, accent, background |
tempest | Tempest polygonal tube: spokes + receding rings | primary, accent, info, background |
fireworks | Vector fireball bursts (Star Wars arcade) | primary, accent, info, semantic palette |
Text presets (Canvas2D)
Type as the background. Set the copy with the text attribute; all honor palette="rainbow|theme|mono".
| Name | Visual | Tokens used |
|---|---|---|
crawl | Star Wars-style perspective text crawl | primary, foreground, background |
marquee | Scrolling vector ticker (outline type) | primary, accent, info, foreground |
sinescroll | Demoscene sine-wave scroller | primary, accent, info, foreground |
cascade | Letters drop & bounce in, hold, loop | primary, accent, info, foreground |
Dataviz presets (Canvas2D)
Animated chart backgrounds — pair with an opaque content panel on top.
| Name | Visual | Tokens used |
|---|---|---|
trades | Trading terminal: scrolling ticker columns + candles | primary, success, error, foreground |
dashboard | Streaming area-line, bouncing bars, sweep gauge | primary, accent, info, foreground |
vectormap | Node map with arcs + traveling packets | primary, accent, info, foreground |
scatter | Drifting clusters of varied vector glyphs | primary, accent, info, foreground |
waveform | Stacked waveform ridgelines (Joy-Division plot) | primary, accent, background |
wordcloud | Drifting, breathing word cloud (reads text) | primary, accent, info |
Canvas2D particle presets
| Name | Visual | Tokens used |
|---|---|---|
stars | Slow-drifting starfield (parallax at intensity > 0.5) | foreground, background |
snow | Falling flakes with horizontal drift | foreground, background |
confetti | Continuous drop in semantic palette | primary, accent, success, warning, error |
network | Connected-dots mesh | primary, foreground |
particles | Generic drift — honors palette. | per palette |
pulse | Concentric rings from center | primary, accent, info |
tetris | Ambient falling tetrominoes | primary, accent, info, success, warning, error |
matrix | Falling digital rain with glyph trails | primary, foreground, background |
mystify | Windows "Mystify" bouncing polyline screensaver | primary, accent, info, background |
Canvas2D pattern & geometric presets
| Name | Visual | Tokens used |
|---|---|---|
mosaic |
Refined squares. mode: isometric (default),
flat, sparse, stacked. |
primary, accent, background |
ribbons |
Bezier wave ribbons with crisp top-edge strokes. | primary, accent, info, background |
source |
Faded HTML source listing. Set text attribute to override
with custom source. |
primary, foreground, background |
system7 |
Drifting Mac windows on 50% stipple. Add use-theme to
honor theme tokens; otherwise black-on-white. |
primary, background (when use-theme set) |
atomic |
Mid-century atomic-age shapes — boomerangs, kidneys, starbursts.
mode: mixed (default), boomerangs,
starbursts, harlequin. |
primary, accent, info, background |
Dimensional / CSS-3D presets
Built with DOM + CSS 3D transforms (the css3d renderer) rather
than a canvas, so they compose with theme tokens and pause cleanly. Motion
lives in CSS keyframes; snapshot() returns null for
these. Use density to scale scene complexity and speed
for tempo.
| Name | Visual | Tokens used |
|---|---|---|
fly-through |
A rotating tunnel of theme-colored segments. mode composes
space-delimited axes: motion orbit (default, rotates the whole
tunnel in view) | fly (camera flies through it); profile
ring (default) | corridor | hex |
tube; path straight | helix |
wave; unit cube | sphere |
pyramid | card. palette="spectrum" for a
rainbow instead of theme colors. |
primary, accent, info |
explode |
A field of particles over a floor grid that bursts outward and
reassembles. mode: radial (default scatter) |
cube (axis-aligned burst). seed fixes the scatter. |
primary, background, foreground |
Ornamental presets
| Name | Visual | Tokens used |
|---|---|---|
girih |
Islamic periodic star-polygon strapwork lattice. mode:
8fold (default), 12fold, 6fold. |
primary, accent, info, background |
mandala |
Layered concentric, counter-rotating radial symmetry; petal motifs keyed to ring, colors cycling outward. | primary, accent, info, background |
op-art |
Optical illusion with false motion. mode: riley
(default), cafewall, moire, drift. |
foreground, background |
Reduced motion
prefers-reduced-motion: reduce triggers the same code
path as motion="reduce" on the element:
- If the
fallbackslot has content → show the slot, hide the canvas. - Else if the preset declares a
staticFrame()method → render one frame attime=0, seed=seed, then halt the RAF loop. - Else → hide the canvas and let the host's CSS background show through.
All shipped presets implement staticFrame().
Performance
- Default
pixel-ratioclamps tomin(devicePixelRatio, 2). 5K monitors don't pay the full GPU bill by default. - Frame budget target: under 4 ms / frame on an M1-class device at 1080p for any v1 preset.
- Particle counts: preset-specific caps of ~500 (med), ~1500 (high), ~150 (low).
- Each element runs its own RAF loop — auto-paused when off-screen, when the tab is hidden, when battery is below 20% and unplugged, and on
prefers-reduced-motion. - Each preset is dynamically imported on first use, so a page that uses one preset doesn't ship the others.
Many instances on one page
Browsers cap simultaneous WebGL contexts (commonly ~16). Each
shader-preset <bg-wc> holds one context, so a page that mounts
more than that at once (a full catalog grid, a poster wall) will see the
browser drop the oldest contexts. Canvas2D presets are not affected.
Two ways to stay under the cap:
- Unmount what's not shown. Removing a
<bg-wc>from the DOM frees its context immediately —disconnectedCallbackcallsWEBGL_lose_context. Group presets behind tabs and mount only the active group (see the gallery); switching tabs releases the old contexts before the new ones allocate. - Group the catalog. The registry tags each preset with a
group;listGroups()returns them as{ id, label, presets }so tooling can build a grouped UI without loading any preset modules.
Recipes
Halftone overlay on flat shapes
Two layered presets (aurora behind stars)
The top layer must declare a transparent background or its
Canvas2D clearRect + bg-fill will mask the layer below.
Section background via data-background
Hot-swap presets at runtime
Snapshot to file
Conic spotlight border
Put a conic behind a panel inset by a hair; only the rim shows, so the border sweeps with light. No @property shim required.
Scroll-linked background
The component re-reads --bg-wc-intensity / --bg-wc-speed (and color tokens) every frame, so driving them from a scroll handler is all it takes.
Whole-page film grain
Browser support
Targets Chromium, Firefox, and Safari at current stable versions. Requires WebGL1 (universally available) for shader presets; Canvas2D presets work anywhere a custom element is registered.
Optional features and their graceful degradations:
| Feature | Fallback if unavailable |
|---|---|
WebGL2 | WebGL1 context attempted automatically. |
OffscreenCanvas | Main-thread rendering. No behavioral change. |
navigator.getBattery() | Battery-aware pause is skipped. |
backdrop-filter | Glass effects in some demos lose blur; layout intact. |
ElementInternals.states | :focus-within child-focus state is skipped. |