effects 65.8 KB gzip charts add-on 34.2 KB core 2.6 KB MIT · 0 dependencies

Effix JavaScript effects

Effects that need JavaScript — particles — applied with classes, tuned with data-efx-*.

Built as the partner of Shine CSS: Shine handles styling with zero JS, Effix adds behaviour and reads Shine's tokens, so tone-* classes and --sh-primary recolour every effect. Only the features found on the page start; heavy ones wait until they scroll into view.

Drop it in your <head>

<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/asticore/shine@main/dist/shine.min.css">
<script src="https://cdn.jsdelivr.net/gh/asticore/effix@main/dist/effix.auto.min.js" defer></script>

Then add classes: efx-reveal, efx-particles, efx-tilt…

Quick start

Four ways in

1 · Auto-loader easiest

One tag. It looks for efx-* classes and fetches only those features' small files; charts, diagrams and visualisations add one shared chart toolkit file the first time one appears. Add class="efx-confetti" to a button and the confetti file loads by itself. With <html data-efx-observe> it also loads files for elements added later.

<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/asticore/shine@main/dist/shine.min.css">
<script src="https://cdn.jsdelivr.net/gh/asticore/effix@main/dist/effix.auto.min.js" defer></script>

2 · Pick files yourself

The core plus one tag per feature, from dist/features/. Tag order doesn't matter.

<script src="https://cdn.jsdelivr.net/gh/asticore/effix@main/dist/effix.core.min.js" defer></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/asticore/effix@main/dist/effix.core.min.css">
<!-- then one tag per feature you use -->
<script src="https://cdn.jsdelivr.net/gh/asticore/effix@main/dist/features/confetti.min.js" defer></script>
<script src="https://cdn.jsdelivr.net/gh/asticore/effix@main/dist/features/particles.min.js" defer></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/asticore/effix@main/dist/features/particles.min.css">

3 · Everything bundled

All effects in one file, plus the optional charts add-on. Best when a site uses many features on every page.

<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/asticore/shine@main/dist/shine.min.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/asticore/effix@main/dist/effix.min.css">
<script src="https://cdn.jsdelivr.net/gh/asticore/effix@main/dist/effix.min.js" defer></script>

<!-- optional: charts & funnels add-on -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/asticore/effix@main/dist/effix-charts.min.css">
<script src="https://cdn.jsdelivr.net/gh/asticore/effix@main/dist/effix-charts.min.js" defer></script>

<!-- optional: diagrams add-on (tree, flow, sequence, cycle, fishbone) -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/asticore/effix@main/dist/effix-diagrams.min.css">
<script src="https://cdn.jsdelivr.net/gh/asticore/effix@main/dist/effix-diagrams.min.js" defer></script>

4 · npm / bundlers

Import the bundle, or only the features you use from the ES sources.

npm i effix shine-css

import 'shine-css';
import 'effix/css';
import Effix from 'effix';            // all effects

// or pick features:
import { define, init } from 'effix/core';
import reveal from 'effix/features/reveal';
import funnel from 'effix/charts/chart-funnel';
define(reveal, funnel);
init();

How it works

Class turns it on, attributes tune it, variables style it

Every feature follows one pattern, so learning one teaches all.

<button class="btn tone-accent efx-border-spin efx-magnetic"
        data-efx-strength="0.4"
        style="--efx-border-speed:2s">
  Subscribe
</button>
  1. efx-* class — picks the feature. Combine as many as you like on one element.
  2. data-efx-* attributes — behaviour options (counts, speeds, triggers). Each feature lists its options below.
  3. --efx-* CSS variables — visual knobs. Colors fall back to Shine: --efx-color → --sh-tone → --sh-primary.
  4. Speed — on load the core asks the page once per feature (querySelectorAll); missing features cost nothing. Canvas features are lazy and every loop pauses off-screen and in hidden tabs.
  5. Accessible by default — reduced-motion users get the static end state, pointer effects only run with a mouse, content is visible without JS.

Page-level switches

SwitchEffect
<html data-efx-manual>Do not auto-start. Call Effix.init() yourself.
<html data-efx-observe>Auto-start features on elements added later (SPAs, visual editors, infinite lists).
<html data-efx-reduce>Force reduced motion (static end states), e.g. for an editor canvas or a user toggle.
<html data-efx-margin="200px">How early lazy features (particles…) start before entering the viewport.
data-efx-skipOn any element: observe() ignores nodes inside it.
data-efx-media="(min-width: 768px)"On any element: its effects run only while the media query matches, and start/stop as the viewport crosses it (e.g. particles on desktop only).
window.EffixConfig = { auto:false, observe:true }Same switches from JS, set before the script loads.

Custom build

Ship only what you use

The full build is already small, but you can cut it further. Tick features to see the size and the command.

Features

Estimated: 100.0 KB gzip

node build.js
import { define, init } from 'effix/core';

Visual editors & SPAs

Works when the page keeps changing

Page builders re-render blocks constantly. Turn on observe and Effix starts new blocks and cleans up removed ones. When the editor changes an option, call Effix.refresh(el).

<html data-efx-observe>
…
// editor changed a block's settings
block.dataset.efxCount = 80;
Effix.refresh(block);

// editor canvas: keep things still while editing
document.documentElement.toggleAttribute('data-efx-reduce', editing);
MethodWhat it does
Effix.init(root?)Scan root (default document) and start every feature found. Safe to call again — already-running elements are skipped.
Effix.destroy(root?, name?)Stop features on root and its children, removing listeners, timers and injected nodes.
Effix.refresh(el, name?)destroy + init: re-reads data-efx-* after you change them.
Effix.observe(target?)Watch the DOM: new nodes start automatically, removed nodes are cleaned up. Same as <html data-efx-observe>.
Effix.disconnect()Stop watching the DOM.
Effix.define(feature)Register your own feature ({ name, selector, defaults, init }).
Effix.features()Names of the features in this build.
Effix.isMounted(el, name)Whether a feature is running on el.
Effix.setData(el | selector, data)Push new data into a chart or odometer (fires efx:data). See Data input.
Effix.add(kind, name, impl)Register a plugin: particle shape, divider shape, ambient mode, easing, chart format… See Extend.
Effix.get(kind, name) · Effix.list(kind)Look up / list registered plugins.
Effix.chartsThe chart toolkit (chart, COMMON, scales, nice, linePath, arcPath, s, axes…) for building your own chart types.

Data input

Five ways to give a chart its data

Every chart reads the same data shape. Pick whichever way suits your page; when several are present the order of precedence is: JavaScript update → table → data-efx-data → inline JSON.

The shape

{
  "labels": ["Mon", "Tue", "Wed"],          // x categories / slices / stages
  "series": [
    { "name": "Web",    "data": [12, 19, 7] },
    { "name": "Mobile", "data": [9, 14, 11], "color": "#db2777" }   // color optional
  ]
}

Shorthands also work: a flat list [12, 19, 7], a list of series [[3,5,2],[4,1,6]], or label/value pairs [{"label":"Mon","value":12}]. Charts with special data (scatter, candlestick, timeline, flow, heatmap calendar) show their own format in a blue Data format box below.

1 · Attribute, comma list

Quickest. Separate series with |, name them with data-efx-names.

<div class="efx-chart-bar"
     data-efx-data="12,19,7|9,14,11"
     data-efx-labels="Mon|Tue|Wed"
     data-efx-names="Web|Mobile"></div>

2 · Attribute, JSON

Any shape above. Wrap the attribute in single quotes so the JSON can use double quotes.

<div class="efx-chart-line"
     data-efx-data='{"labels":["Mon","Tue","Wed"],
                     "series":[{"name":"Web","data":[12,19,7]}]}'></div>

3 · Inline JSON script

Best for bigger data or server-rendered pages: put a JSON script inside the chart element.

<div class="efx-chart-pie">
  <script type="application/json">
    { "labels": ["Organic", "Direct", "Social"],
      "series": [{ "name": "Visits", "data": [4200, 2800, 900] }] }
  </script>
</div>

4 · A Shine table

Keep one accessible table and chart it. First column = labels, header row = series names.

<table class="table" id="sales">
  <thead><tr><th>Month</th><th>2025</th><th>2026</th></tr></thead>
  <tbody><tr><td>Jan</td><td>42</td><td>51</td></tr> …</tbody>
</table>
<div class="efx-chart-bar" data-efx-source="#sales"></div>

5 · JavaScript

Load or update data at any time (API calls, live dashboards). Same shape as above.

// any time after Effix has loaded
Effix.setData('#sales-chart', {
  labels: ['Jan', 'Feb', 'Mar'],
  series: [{ name: 'Revenue', data: [42, 58, 51] }],
});

// e.g. from your API
fetch('/api/sales').then(r => r.json())
  .then(data => Effix.setData('#sales-chart', data));

Live: update from JavaScript

document.querySelector('#data-demo-btn').onclick = () =>
  Effix.setData('#data-demo', {
    labels: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri'],
    series: [
      { name: 'Web',    data: Array.from({ length: 5 }, () => 5 + Math.round(Math.random() * 25)) },
      { name: 'Mobile', data: Array.from({ length: 5 }, () => 5 + Math.round(Math.random() * 25)) },
    ],
  });

Extend Effix

Add your own shapes, modes, formats, charts and features

Built-in variants are registered through the same plugin registry you use, so yours are first-class: register once, then use the name in data-efx-* like any built-in.

Register before Effix starts with window.EffixConfig.extend (put it in a normal <script> above the Effix tags), or any time later with Effix.add(…) followed by Effix.refresh(el). This page runs exactly the code on the right:

Custom particle shape
data-efx-shape="heart"
Custom chart type + format
KindUsed bySignature
CSSAnimations, Reveal on scroll--efx-anim
EventsScene reelefx:scene
easingCounter, Scroll scrub(t: 0..1) => number
sparkle-shapeSparklesfn(size) -> svg markup string or Node
confetti-shapeConfetti(ctx, size, piece) => void
ambient-modeAmbient backgrounds{ count(area)->n, spawn(p,S,first), step(p,S)->alive, draw(ctx,p,S), blend?, ptr? }
particle-shapeParticles(ctx2d, size, particle) => void
trail-shapeCursor trail(size, arg) => Node
divider-shapeShape dividers{ periodic: 0|1, layers: [[y0, side, tile(ox) -> "L x,y…"]], ops?: [opacity…] }
Effix.addShape morph'shape', name, d
audio-vizAudio visualizer(ctx2d, { freq, time, level, count }, w, h, colors) => void
AttributesPricing toggle[data-efx-period]
EventPricing toggle, Toastefx:period
TriggerToast[data-efx-toast="#id"]
formatAll charts (data-efx-format)(value, options) => string
Effix.defineYour own feature or chart type{ name, selector, lazy?, defaults, init(el, opts) → cleanup }
window.EffixConfig = {
  extend(E) {
    // 1. A particle shape: draw centred on 0,0 at the given size (fill colour is already set).
    E.add('particle-shape', 'heart', (ctx, size) => {
      const s = size / 2;
      ctx.beginPath();
      ctx.moveTo(0, s * 0.6);
      ctx.bezierCurveTo(-s * 1.4, -s * 0.4, -s * 0.5, -s * 1.3, 0, -s * 0.5);
      ctx.bezierCurveTo(s * 0.5, -s * 1.3, s * 1.4, -s * 0.4, 0, s * 0.6);
      ctx.fill();
    });

    // 2. A number format any chart can use with data-efx-format="gbp".
    E.add('format', 'gbp', v => '£' + Math.round(v).toLocaleString('en-GB'));
  },
};

// 3. A whole new chart type built on the chart toolkit (Effix.charts),
//    and 4. a tiny custom feature. Both work like built-ins: class + data-efx-*.
document.addEventListener('efx:ready', ({ detail: E }) => {
  const { chart, COMMON, nice, linear, axes, s } = E.charts;

  E.define({
    name: 'chart-dots',
    selector: '.efx-chart-dots',
    lazy: true,
    defaults: { ...COMMON, radius: 6 },
    init: (el, o) => chart(el, o, ({ g, w, h, data, visible, colors, fmt }) => {
      const pad = { t: 10, r: 10, b: 28, l: 48 };
      const sc = nice(0, Math.max(1, ...visible.flatMap(sr => sr.values)));
      const y = linear([sc.min, sc.max], [h - pad.b, pad.t]);
      const x = i => pad.l + (i + 0.5) * (w - pad.l - pad.r) / data.labels.length;
      axes(g, { w, h, pad, y, ticks: sc.ticks, labels: data.labels, x, fmt });
      const marks = [];
      visible.forEach(sr => sr.values.forEach((v, i) => {
        s('line', { x1: x(i), x2: x(i), y1: y(0), y2: y(v), stroke: colors[sr.index], 'stroke-width': 2 }, g);
        const node = s('circle', { cx: x(i), cy: y(v), r: o.radius, fill: colors[sr.index], class: 'efx-chart__mark' }, g);
        marks.push({ x: x(i), y: y(v), label: data.labels[i], value: v, series: sr.name, node, index: i });
      }));
      return marks; // tooltips, keyboard, legend and efx:select come free
    }),
  });

  E.define({
    name: 'blink',
    selector: '.my-blink',
    defaults: { speed: 600 },                  // read from data-efx-speed
    init(el, o) {
      const t = setInterval(() => el.classList.toggle('is-on'), o.speed);
      return () => { clearInterval(t); el.classList.remove('is-on'); }; // cleanup
    },
  });
});

Features

112 features

Every demo is live: edit the HTML under it and the demo restarts with your options.

Animations

animate 3.0 KB

Ready-made keyframe animations as classes (fade, bounce, slide, pop, rotate, zoom, flip, plus attention seekers) with triggers: hover, focus, active, load, click, scroll. Plus underline animations. Class alone plays once on load.

Fade in up
Bounce in
Pop elastic
Flip X
Center underline Grow underline
ClassWhat it does
efx-fade-in · efx-fade-out · efx-fade-in-up · efx-fade-in-downFades. Entrance anims start hidden.
efx-bounce · efx-bounce-in · efx-bounce-out · efx-bounce-up · efx-bounce-downBounces (entrance, exit, directional).
efx-slide-up · efx-slide-down · efx-slide-left · efx-slide-rightSlides from the element's own size.
efx-pop · efx-pop-in · efx-pop-elastic · efx-rotate · efx-rotate-in · efx-spin · efx-spin-reversePop, rotate and continuous spin (spin loops by default).
efx-scale-up · efx-scale-down · efx-zoom-in · efx-zoom-out · efx-flip-x · efx-flip-y · efx-flip-3d · efx-shakeScale, zoom and 3D flips.
efx-wobble · efx-pulse · efx-heartbeat · efx-jello · efx-tada · efx-swing · efx-rubberAttention seekers.
efx-animGeneric: plays whatever --efx-anim names (use with your own keyframes).
efx-hover · efx-focus · efx-activeTrigger (pure CSS): play on hover, focus-visible/focus-within, or while pressed.
efx-loadTrigger: plays once on load (the default with no trigger class; supports .efx-stagger).
efx-clickTrigger: replays on every click.
efx-scrollTrigger: plays when scrolled into view (entrance anims stay hidden until then, only once JS runs).
efx-loopRepeat forever (or data-efx-repeat="3").
efx-underline-growUnderline that grows in on hover/focus and leaves out the other side.
efx-underline-left · efx-underline-right · efx-underline-centerUnderline wipes in from that origin on hover/focus-visible.
efx-staggerContainer: cascades delays of .efx-load / .efx-scroll children (data-efx-stagger="80").
AttributeDefaultValues
data-efx-delay0Extra delay in ms (click/load/scroll triggers).
data-efx-oncetrueefx-scroll: false = replay each time it re-enters.
data-efx-threshold0.15efx-scroll: how far into the viewport (0-1) before it plays.
data-efx-repeatIteration count (number or "infinite"); CSS handles 2-5 and infinite without JS.
data-efx-stagger80On .efx-stagger: ms between children.
data-efx-fromfirstOn .efx-stagger: where the cascade starts: first · last · center · edges · random · or an item index (0-based).
data-efx-gridOn .efx-stagger: "cols,rows" (e.g. "4,3") or "auto" (measures item positions) to delay by 2D distance from the origin.
data-efx-axisOn .efx-stagger with a grid: x or y to measure distance on one axis only.
data-efx-easelinearOn .efx-stagger: easing name (see Effix.add("easing")) distributing the delays along a curve.
data-efx-totalOn .efx-stagger: spread the cascade across this many ms in total instead of ms per step.
CSS variableDefaultControls
--efx-duration700msAnimation length.
--efx-easecubic-bezier(.22,1,.36,1)Easing.
--efx-delay0sStart delay.
--efx-iter1Iteration count.
--efx-distance24pxTravel for fade-in-up/down.
--efx-colorShine tone/primaryUnderline color.
--efx-thickness2pxUnderline thickness.

Extend it

KindSignatureWhat it is
CSS--efx-animCustom animation in pure CSS: `@keyframes efx-wiggle { 50% { rotate: 8deg } } .efx-wiggle { --efx-anim: efx-wiggle }` then `class="efx-anim efx-wiggle efx-hover"`. All triggers and iteration knobs work.

Nudge

nudge 1.1 KB

Repeats a small attention animation (shake, wobble, bell ring or any animate.css effect) on an element until the user clicks or hovers it. Only runs while the element and tab are visible. Optional pulsing notification dot. Reduced motion shows only the static dot.

ClassWhat it does
efx-nudgeElement to nudge (button, bell icon, CTA).
AttributeDefaultValues
data-efx-every6000Ms between nudges.
data-efx-animshakeshake · wobble · ring, or any animate.css name (pulse, tada, heartbeat, jello...).
data-efx-times0Max repeats (0 = until interaction).
data-efx-delay3000Ms before the first nudge.
data-efx-stopclickclick · hover · never.
data-efx-dotfalseAdd a pulsing notification dot top-right (hides on interaction).
CSS variableDefaultControls
--efx-nudge-dotvar(--sh-danger)Dot color.

Scene reel

reel 2.6 KB

A showreel sequencer: scenes play one after another with fade, slide, wipe or zoom transitions. Effects inside each scene replay as it enters. Play/pause, clickable progress segments, keyboard, pauses offscreen. Manual and cut-only with reduced motion.

Meet Effix

Motion for Shine, in one script.

Slide right in

Each scene replays its own effects.

Wipe it clean

Clip-path reveal.

Zoom finale

Loop, pause, or jump with the bar.

ClassWhat it does
efx-reelThe container. Its scene children play in order.
efx-reel__sceneA scene (or use [data-efx-scene]). Only the current one is visible; the rest are hidden and inert.
AttributeDefaultValues
data-efx-autoplaytrueStart playing when visible (never with reduced motion).
data-efx-loopfalseRestart after the last scene.
data-efx-controlstrueInject play/pause button and progress segments.
data-efx-duration3000Default scene length in ms (override per scene).
data-efx-transitionfadeDefault transition: fade · slide · wipe · zoom · cut (override per scene).
CSS variableDefaultControls
--efx-reel-t600msTransition length.
--efx-colorShine toneProgress fill color.

Extend it

KindSignatureWhat it is
Eventsefx:sceneFires on the container with detail.index whenever a scene is entered. Keys: ← → switch scenes, Space plays/pauses.

ASCII art

ascii 2.4 KB

Turns an image, video, canvas or big text into ASCII art in a

 (or canvas) by sampling luminance per cell. Characters scramble then settle when it scrolls into view; videos render live at a capped fps. The original stays in the DOM (visually hidden) for assistive tech; the art is aria-hidden. Images need to be same-origin or CORS-enabled, otherwise the original is shown and a warning logged. Reduced motion: static render.

A smiling face
A smiling face
ClassWhat it does
efx-asciiOn an <img>, <video>, <canvas>, or a block element with data-efx-text.
efx-ascii__outInjected <pre> (or <canvas>) holding the art.
efx-ascii__srcAdded to the original image/video/canvas while it is replaced.
AttributeDefaultValues
data-efx-cols80Characters per row (rows follow the aspect ratio).
data-efx-chars .:-=+*#%@Characters from dark to bright.
data-efx-invertfalseFlip the brightness mapping (use on light backgrounds).
data-efx-colormonomono (inherits text color, or --efx-ascii-color) · source (per-character color from the image).
data-efx-textRender this text large and convert it (use "&#10;" for line breaks). Falls back to the element's own text.
data-efx-outputprepre · canvas.
data-efx-revealtrueScramble-then-settle animation when first visible.
data-efx-duration1200Reveal length in ms.
data-efx-fps24Frame cap for the reveal and live video.
data-efx-livefalseOn a <canvas> source: re-sample every frame. Videos are always live while playing.
CSS variableDefaultControls
--efx-ascii-colorinheritText color of the art.

Distort

distort 0.8 KB

Liquid ripple warp from an inline SVG filter (feTurbulence + feDisplacementMap) on images or any element. Animates only while active and eases back; no effect with reduced motion.

Rings

hover

Mountain

always

Any element

Text warps too.

ClassWhat it does
efx-distortImage or element to warp. One hidden <svg><filter> per instance, removed on cleanup.
AttributeDefaultValues
data-efx-scale30Maximum displacement in px.
data-efx-frequency0.02Noise base frequency (lower = broader waves).
data-efx-speed1Animation speed multiplier.
data-efx-triggerhoverhover · always (while on screen) · view (one pulse when scrolled in).

Flip card

flip 0.9 KB

A card that flips in 3D on hover (or on click / Enter / Space). Height is the taller face, so nothing is clipped. Reduced motion crossfades instead of rotating.

Mountain at sunrise
Hover to flip

Back side

Any content, any height.

City skyline
Click, Enter or Space (vertical)

Flipped

Press again to flip back.

ClassWhat it does
efx-flipThe card wrapper.
efx-flip__frontFront face (child of .efx-flip).
efx-flip__backBack face (child of .efx-flip). Hidden from assistive tech until shown.
AttributeDefaultValues
data-efx-triggerhoverhover · click. Click mode makes the card a button with aria-pressed. Touch devices always use click.
data-efx-axisyy (horizontal flip) · x (vertical flip).
data-efx-duration600Flip time in ms.
CSS variableDefaultControls
--efx-easecubic-bezier(.22,1,.36,1)Easing.

Ken Burns

kenburns 1.0 KB

Slow pan and zoom with a random origin and direction per image. Several images in one wrapper become a crossfading slideshow. Pauses off-screen; static with reduced motion.

Mountain

single image

RingsCityMountain

slideshow

ClassWhat it does
efx-kenburnsAn <img> (gets wrapped in a clipping frame) or a wrapper holding one or more <img>.
AttributeDefaultValues
data-efx-duration12000Pan/zoom length in ms; also the slideshow interval.
data-efx-zoom1.15End zoom factor.
CSS variableDefaultControls
--efx-kb-x0 … --efx-kb-y1randomPer-image start/end translation, set by JS.

Pixelate

pixelate 1.0 KB

Mosaic that sharpens into the real image when it scrolls into view, or pixelates on hover. Draws with canvas drawImage only (no pixel reads), so cross-origin images work. Reduced motion shows the plain image.

Mountain

trigger: view

City

trigger: hover

ClassWhat it does
efx-pixelateThe <img>, or a wrapper that contains one.
AttributeDefaultValues
data-efx-from32Largest block size in px.
data-efx-duration900Transition time in ms.
data-efx-triggerviewview (sharpen on scroll-in) · hover (pixelate on hover, sharpen on leave).

Poster pop-out

popout 1.0 KB

A background image stays clipped to the card while a transparent cut-out bursts out of the frame. Pointer movement and scroll shift the layers at different depths with a slight 3D tilt. Static overflow look with reduced motion.

A ringed planet bursting out of the frame
ClassWhat it does
efx-popoutThe card (give it a size and a radius).
efx-popout__bgBackground layer, clipped to the card. A div with background-image, or an img.
efx-popout__fgForeground cut-out (transparent PNG/SVG img) that overflows the top and sides.
AttributeDefaultValues
data-efx-depth20Layer travel in px (foreground moves most, background least).
data-efx-tilt8Maximum 3D tilt in degrees (pointer).
data-efx-modebothpointer · scroll · both (pointer needs a fine pointer; scroll works on touch).

Spotlight mask

mask 1.0 KB

A circular spotlight follows the pointer and reveals the colour image over a greyscale base. Tap or press Enter to toggle the full reveal on touch and keyboard.

Mountain at sunrise
City by day
ClassWhat it does
efx-maskWrapper containing the base <img>.
efx-mask__revealOptional second <img> shown inside the spotlight. Without it a colour copy of the base is used.
AttributeDefaultValues
data-efx-radius120Spotlight radius in px (grows in on enter).
data-efx-soft0.4Edge softness 0–1.
data-efx-graytruefalse = leave the base image in colour (use with a different reveal image).
CSS variableDefaultControls
--efx-x / --efx-y / --efx-rset by JSSpotlight position and radius, readable for custom styling.

Back to top

totop 0.6 KB

A button that fades in after scrolling and returns to the top (smooth when motion is allowed).

Appears after scrolling 100px.
ClassWhat it does
efx-totopThe button. Fixed bottom-right by default; gets is-shown after scrolling.
AttributeDefaultValues
data-efx-show400Scroll distance in px before it appears.
data-efx-fixedtruefalse = no fixed positioning, place it yourself.

Chapter indicator

chapter 1.5 KB

A chip that shows the title of the section currently in view. The text slides up when the section changes and a ring tracks progress through that section. Clicking scrolls to the section.

Discover

Build

Ship

ClassWhat it does
efx-chapterThe chip (usually position:fixed or sticky). Gets is-empty while no section is in view.
AttributeDefaultValues
data-efx-sectionssection[data-efx-title]CSS selector of the sections. Title comes from data-efx-title or the first heading.
data-efx-ringtrueShow the section progress ring.
CSS variableDefaultControls
--efx-chapter-bgsurface 85%Chip background.
--efx-colorShine tone/primaryRing color.

Counter

counter 0.8 KB

Counts up to the number written in the element when it scrolls into view. Without JS (or with reduced motion) the final value shows.

12840
Users
9.99
Price
99
Uptime
ClassWhat it does
efx-counterElement whose text is the final number.
AttributeDefaultValues
data-efx-from0Start value.
data-efx-tofrom textEnd value (defaults to the number in the text).
data-efx-duration1600Duration in ms.
data-efx-easeease-out-cubiclinear · ease-in · ease-out · ease-in-out · ease-out-cubic · back-out · elastic-out, or any registered easing.
data-efx-decimals-1Decimal places; -1 = infer from the target.
data-efx-separator,Thousands separator.
data-efx-prefix""Text before the number, e.g. $.
data-efx-suffix""Text after the number, e.g. + or %.
data-efx-oncetruefalse = replay every time it re-enters the viewport.

Extend it

KindSignatureWhat it is
easing(t: 0..1) => numberShared with scrub (data-efx-ease). Return 0..1 (overshoot allowed).
<script>
window.EffixConfig = { extend(E) {
  E.add('easing', 'steps4', t => Math.floor(t * 4) / 4);
} };
</script>
<span class="efx-counter" data-efx-ease="steps4">1000</span>

Horizontal scroll

hscroll 1.0 KB

Pins a section while vertical scrolling slides a row of panels sideways. On small screens or with reduced motion it becomes a native swipeable row.

One

Keep scrolling down.

Two

The page moves sideways.

Three

Then continues down.

ClassWhat it does
efx-hscrollThe section. Its height is computed from the track width.
efx-hscroll__trackOptional child holding the panels. Added automatically if missing.
AttributeDefaultValues
data-efx-offset0Pin this many px below the top (for a sticky header).
data-efx-snapfalseSettle on the nearest panel when scrolling stops.

Marquee

marquee 0.9 KB

Infinite scrolling ticker. Content is cloned (aria-hidden) to fill the width; pauses on hover/focus and when off-screen; wraps statically with reduced motion.

AlphaBetaGammaDeltaEpsilon
ClassWhat it does
efx-marqueeContainer whose children scroll endlessly.
AttributeDefaultValues
data-efx-speed60Pixels per second.
data-efx-directionleftleft · right
data-efx-pausetruePause on hover and keyboard focus.
data-efx-gap32Space between items in px.
CSS variableDefaultControls
--efx-gapset from data-efx-gapSpace between items.

Motion path

path 1.5 KB

An element travels along an SVG path, driven by scroll, a loop or a one-shot play, rotating with the tangent and leaving a drawn trail.

➤ ➤
ClassWhat it does
efx-pathContainer. Give it data-efx-svg (an existing svg/path) or data-efx-d (path data, drawn for you).
efx-path__itemChild that travels the path (several are spaced by data-efx-gap). Its center sits on the path.
AttributeDefaultValues
data-efx-modescrollscroll = progress of the container through the viewport · loop = repeat every duration · view = play once when seen.
data-efx-dPath data to draw inside an svg the feature creates, scaled to the container.
data-efx-viewbox0 0 1000 300viewBox for data-efx-d; the container gets this aspect ratio if it has no height.
data-efx-svgSelector of an existing <svg> or <path> to follow instead of data-efx-d.
data-efx-duration4000ms per trip (loop and view).
data-efx-rotatetrueRotate the item to the path tangent.
data-efx-show-pathtrueDraw the path with a trail that grows behind the leading item.
data-efx-start0Where on the path (0–1) the trip begins.
data-efx-end1Where on the path (0–1) the trip ends.
data-efx-gap0.08Spacing between multiple items, as a fraction of the path.
CSS variableDefaultControls
--efx-colorvar(--sh-primary)Trail color.

Odometer

odometer 1.0 KB

Rolling digit counter: each digit is a 0-9 strip that rolls into place when visible. Re-roll live with an efx:data event. Static final value without JS or with reduced motion.

$12,840
ClassWhat it does
efx-odometerElement whose text is the final number. Non-digits ($ , % .) stay static.
AttributeDefaultValues
data-efx-duration1800Roll time in ms.
data-efx-fromStart value (empty = zeros).
data-efx-stagger60Delay between digits in ms.
data-efx-oncetruefalse = reset and replay when re-entering the viewport.
CSS variableDefaultControls
--efx-odo-duration1800msSet from data-efx-duration.

Parallax

parallax 0.7 KB

Moves an element slower, faster or opposite to the scroll. Only computes while visible; static with reduced motion.

Slow drift
Opposite drift

Background parallax

The gradient layer moves behind this text.

ClassWhat it does
efx-parallaxShift this element (or its background image with data-efx-bg) as the page scrolls.
AttributeDefaultValues
data-efx-speed0.3Strength, -1 to 1. Negative moves against the scroll.
data-efx-axisyy · x
data-efx-bgfalseMove the CSS background-image through an injected oversized layer instead of the element.

Reveal on scroll

reveal 1.6 KB

Fades, slides, zooms or blurs elements in as they enter the viewport. Content stays visible without JS.

Fade up
Zoom
Blur
Wipe up
Rise
Scale down
1
2
3
4
5
6
7
8
9
10
11
12
ClassWhat it does
efx-revealAnimate this element in when it scrolls into view.
efx-staggerContainer: cascades the delay of every .efx-reveal inside it.
AttributeDefaultValues
data-efx-revealfade-upfade · fade-up · fade-down · slide-left · slide-right · zoom · blur · flip · wipe-up · wipe-left · wipe-right · rise · scale-down
data-efx-delay0Extra delay in ms.
data-efx-oncetruefalse = hide again when it leaves the viewport.
data-efx-threshold0.15How far into the viewport (0–1) before it plays.
data-efx-stagger80On .efx-stagger: ms between children.
data-efx-fromfirstOn .efx-stagger: where the cascade starts: first · last · center · edges · random · or an item index (0-based).
data-efx-gridOn .efx-stagger: "cols,rows" (e.g. "4,3") or "auto" (measures item positions) to delay by 2D distance from the origin.
data-efx-axisOn .efx-stagger with a grid: x or y to measure distance on one axis only.
data-efx-easelinearOn .efx-stagger: easing name (see Effix.add("easing")) distributing the delays along a curve.
data-efx-totalOn .efx-stagger: spread the cascade across this many ms in total instead of ms per step.
CSS variableDefaultControls
--efx-duration700msAnimation length.
--efx-easecubic-bezier(.22,1,.36,1)Easing.
--efx-distance24pxTravel distance for fade/slide.

Extend it

KindSignatureWhat it is
CSS[data-efx-anim="name"]Add your own animation in pure CSS: `.efx-reveal-pending[data-efx-anim="myname"] { transform: skewY(6deg); }` then use data-efx-reveal="myname". Define the hidden state; .is-in clears it.

Scroll progress

progress 0.6 KB

A bar that fills as the page (or one article) is scrolled. Exposes --efx-progress and role="progressbar".

This bar tracks how far you have scrolled through this article.

Keep scrolling the page.

ClassWhat it does
efx-progressThe bar element. Fixed to the top by default.
AttributeDefaultValues
data-efx-target""CSS selector of an article to measure instead of the whole page.
data-efx-positiontoptop · bottom · none (none = you position it).
data-efx-height4Bar thickness in px.
CSS variableDefaultControls
--efx-colorvar(--sh-tone, --sh-primary)Bar color (Shine .tone-* classes work).
--efx-progress0..1Set by JS; use it to style anything else.

Scroll scrub

scrub 0.9 KB

Ties transforms, opacity and blur to how far an element has travelled through the viewport. Works on buttons, images, sections, anything. Neutral with reduced motion.

Rises in
Spins and shrinks
Peaks at center
ClassWhat it does
efx-scrubScrub this element with scroll. Progress is 0 as it enters at the bottom and 1 as it leaves at the top.
AttributeDefaultValues
data-efx-x0Horizontal travel in px (neutral to value).
data-efx-y0Vertical travel in px.
data-efx-rotate0End rotation in degrees.
data-efx-scale1End scale.
data-efx-opacity-1End opacity (0–1). -1 leaves opacity alone.
data-efx-blur0End blur in px.
data-efx-fromAdvanced start state, e.g. "y:60 opacity:0 scale:.8". Keys: x y rotate scale opacity blur.
data-efx-toAdvanced end state, same keys. Overrides the single options.
data-efx-start0Progress (0–1) where the scrub begins.
data-efx-end1Progress (0–1) where it finishes.
data-efx-peaknonecenter = progress is a triangle peaking at 1 when the element center is at the viewport center (images grow as they reach center, shrink after). none = normal 0 to 1.
data-efx-easelinearlinear · ease-in · ease-out · ease-in-out · ease-out-cubic · back-out · elastic-out (in/out/inout aliases), or any registered easing
CSS variableDefaultControls
--efx-p0Written on the element: eased progress 0–1. Use it in your own CSS calc().

Extend it

KindSignatureWhat it is
easing(t: 0..1) => numberShared by scrub and counter (data-efx-ease). Return 0..1 (overshoot allowed).
<script>
window.EffixConfig = { extend(E) {
  E.add('easing', 'steps4', t => Math.floor(t * 4) / 4);
} };
</script>
<div class="efx-scrub" data-efx-ease="steps4" data-efx-y="120"></div>

Scroll sequence

sequence 1.5 KB

Plays an image sequence (canvas) or a video as you scroll through a tall pinned section. Frames load progressively, nearest first. Shows a still frame with reduced motion.

ClassWhat it does
efx-sequenceA div (image sequence) or a video (scrubbed by currentTime). Becomes a tall scroll track with a pinned stage.
AttributeDefaultValues
data-efx-srcFrame URL template with {i}, e.g. frames/f{i}.webp.
data-efx-frames0Number of frames when using src.
data-efx-pad0Zero-pad the frame number to this many digits.
data-efx-start1First frame number.
data-efx-listAlternative to src: frame URLs separated by |.
data-efx-height300Scroll length of the section in vh.
data-efx-fitcovercover · contain

Scrollspy

scrollspy 0.8 KB

Highlights the table-of-contents link whose section is in view and optionally smooth-scrolls on click.

ClassWhat it does
efx-scrollspyNav/TOC containing a[href^="#"] links. The active link gets is-active and aria-current="true".
AttributeDefaultValues
data-efx-offset80Px from the top where a section becomes active (also scroll offset on click).
data-efx-active-classis-activeClass added to the active link.
data-efx-smoothtrueSmooth scroll on click (respects reduced motion).

Stacking cards

stack 0.4 KB

Cards stick near the top and pile up as you scroll; each covered card scales back and dims. Plain sticky cards with reduced motion.

Step one

Scroll on.

Step two

Covers the first.

Step three

And the second.

ClassWhat it does
efx-stackContainer. Every direct child becomes a sticky card.
AttributeDefaultValues
data-efx-offset80Sticky top of the first card in px (clear your header).
data-efx-gap16Extra top px per card so edges peek out.
data-efx-shrink0.05Scale lost per card stacked on top of it.
data-efx-blur0Max blur in px for covered cards.
data-efx-dim0.15Max darkening (0–1) for covered cards.

Sticky header

sticky 0.7 KB

Makes an element position: sticky and adds state classes: is-stuck (with shadow), is-hidden (hide on scroll down) and is-shrunk.

Sticky bar: gets is-stuck (shadow) and is-shrunk while scrolling
Scroll the page so the bar sticks.
ClassWhat it does
efx-stickySticky element. Gets is-stuck, is-hidden, is-shrunk.
AttributeDefaultValues
data-efx-offset0Distance from the top edge in px.
data-efx-hidefalseHide when scrolling down, show when scrolling up.
data-efx-shrinkfalseAdd is-shrunk after scrolling past shrinkAt.
data-efx-shrink-at80Scroll distance in px for is-shrunk.

SVG draw

draw 0.8 KB

Draws SVG strokes in, either scrubbed by scroll or played once when visible. Fully drawn without JS or with reduced motion.

ClassWhat it does
efx-drawOn an <svg>, or a container holding one. Paths, lines, circles, rects… are drawn (or only [data-efx-draw-item] ones).
AttributeDefaultValues
data-efx-modescrollscroll (tied to scroll progress) · view (plays once when visible).
data-efx-duration1500View mode: draw time in ms.
data-efx-start0Scroll mode: progress (0–1) where drawing begins.
data-efx-end0.7Scroll mode: progress (0–1) where drawing finishes.
data-efx-stagger0Per-shape offset: ms in view mode, progress fraction in scroll mode.
data-efx-fillfalseFade the fill in at the end of the drawing.

Glitch text

glitch 0.7 KB

RGB-split glitch effect for headings using clipped, offset copies of the text. Static under reduced motion.

System failure

Hover me

ClassWhat it does
efx-glitchGlitching text (always, or on hover with data-efx-trigger="hover").
AttributeDefaultValues
data-efx-triggeralwaysalways · hover (also on keyboard focus).
data-efx-textOverride the glitch layer text (default: the element text).
CSS variableDefaultControls
--efx-glitch-aShine accentFirst split color.
--efx-glitch-bShine secondarySecond split color.
--efx-glitch-speed2.4sCycle length.
--efx-glitch-bgtransparentBackground of glitch layers (set to the surface color to mask the original).

Kinetic bumper

kinetic 1.4 KB

Kinetic typography: big centered type that shows one word per beat with rotating punch, slide, spin, blur and split entrances, colored from Shine tones. Screen readers get the full sentence; reduced motion shows it statically.

ClassWhat it does
efx-kineticContainer. Words come from data-efx-words (or the element text).
AttributeDefaultValues
data-efx-wordsWords or phrases separated by |.
data-efx-beat600Milliseconds per word.
data-efx-stylespunch|slide|spin|blur|splitEntrance styles, cycled in order.
data-efx-randomfalsePick styles at random instead of cycling.
data-efx-colorsPer-word colors separated by |; defaults to Shine tones.
data-efx-holdfalsetrue = stop on the last word instead of looping.

Morphing text

morph 0.9 KB

Cycles through a list of words with a gooey blur morph: letters melt into the next word. Width is reserved for the longest word so surrounding text never jumps. Screen readers read the current word; reduced motion shows the first word only.

We products

ClassWhat it does
efx-morphInline element whose text morphs. Without data-efx-words the existing text is used (static).
AttributeDefaultValues
data-efx-words(none)Words separated by |, e.g. Design|Build|Ship.
data-efx-duration1200Morph time in ms.
data-efx-pause1800Hold time between morphs in ms.
CSS variableDefaultControls
--efx-morph-justifycenterAlignment of shorter words inside the reserved width (start | center | end).

Proximity

proximity 1.2 KB

Letters or icons scale, thicken, lift and recolor depending on how close the pointer is, like a macOS dock. Fine pointers and motion-OK only.

Hover over these letters

★♥⚡☀✿
ClassWhat it does
efx-proximityText is split into letters (screen readers get the original); with data-efx-mode="items" children marked [data-efx-item] react instead.
efx-proximity__cInjected letter span.
AttributeDefaultValues
data-efx-radius120Distance in px within which pieces react.
data-efx-scale1.4Scale of the closest piece.
data-efx-weight0Target font-weight at the pointer (0 = off). Needs a variable font to look smooth.
data-efx-lift0Upward lift in px.
data-efx-colorColor to mix in near the pointer (empty = off), e.g. var(--sh-primary).
data-efx-modelettersletters · items

Sparkles

sparkles 0.9 KB

Twinkling stars scattered around any element: a headline, a button, a badge. Each star scales and rotates in and out, then reappears somewhere new. Off with reduced motion; pauses off-screen.

Make it sparkle

ClassWhat it does
efx-sparklesHost element. Sparkles are drawn in an overlay (no pointer events) that may overflow the element a little.
AttributeDefaultValues
data-efx-count10Number of stars (max 60).
data-efx-color(theme + gold)One color or a list separated by |.
data-efx-size-min8Smallest star in px.
data-efx-size-max18Largest star in px.
data-efx-speed1Twinkle speed multiplier.
data-efx-shapestarName of a registered sparkle-shape.
CSS variableDefaultControls
--efx-colorShine tone / primaryUsed for the first color when data-efx-color is empty.

Extend it

KindSignatureWhat it is
sparkle-shapefn(size) -> svg markup string or NodeDraw with fill="currentColor" so the star takes its color from data-efx-color.
<script>
window.EffixConfig = { extend(E) {
  E.add('sparkle-shape', 'dot', s => '<svg viewBox="0 0 10 10" width="' + s / 2 + '" height="' + s / 2 + '"><circle cx="5" cy="5" r="5" fill="currentColor"/></svg>');
} };
</script>
<span class="efx-sparkles" data-efx-shape="dot" data-efx-color="#38bdf8|#a855f7"><strong>Dots instead</strong></span>

Split text

split 0.9 KB

Splits a heading into words or letters and animates them in with a stagger when scrolled into view. Screen readers get the original text; no JS or reduced motion = plain text.

Letters rise in

Words fade from blur into focus

Looping wave

ClassWhat it does
efx-splitElement whose text is split and animated. Inline markup inside is flattened.
AttributeDefaultValues
data-efx-bywordword · letter (falls back to word above max pieces).
data-efx-effectfade-upfade · fade-up · blur · slide · wave (looping).
data-efx-stagger40Delay between pieces in ms.
data-efx-duration600Per-piece animation time in ms.
data-efx-oncetruefalse = replay when re-entering the viewport.
data-efx-max200Max letters to split; beyond this, split by word.
CSS variableDefaultControls
--efx-easecubic-bezier(.22,1,.36,1)Easing.

Text fill

textfill 1.0 KB

Apple-style paragraph that lights up word by word as you scroll. Screen readers get the original text; no JS or reduced motion = full-color text.

Scroll this panel into view and every word lights up in turn, one after another, as you move down the page.

ClassWhat it does
efx-textfillElement whose text is split into pieces that fill in with scroll.
AttributeDefaultValues
data-efx-start0.8Viewport fraction (from top) where the element top starts the fill.
data-efx-end0.3Viewport fraction where the element bottom finishes the fill.
data-efx-bywordword · letter.
data-efx-dim0.2Opacity of unfilled text.
data-efx-colorText color once filled (default: current color).
CSS variableDefaultControls
--efx-textfill-dim0.2Opacity of unfilled text.
--efx-textfill-colorcurrentColorFilled text color.

Text scramble

scramble 0.9 KB

Decodes text from random glyphs into the real thing, on view, hover, click or load, or cycles through a list of phrases. Real text stays available to screen readers; reduced motion shows the final text.

Decode this headline

Build faster

ClassWhat it does
efx-scrambleScramble this element's text (headings, spans, buttons).
AttributeDefaultValues
data-efx-triggerviewview · hover · load · click.
data-efx-chars!<>-_\/[]{}—=+*^?#________Glyph pool used while scrambling.
data-efx-speed30Milliseconds per frame.
data-efx-duration900Total decode time in ms.
data-efx-oncetruefalse = replay each time it re-enters the viewport.
data-efx-wordsa|b|c : cycle through these phrases like a rotating headline.
data-efx-pause2000Words mode: ms to hold each phrase.

Typed text

typed 0.9 KB

Typewriter or rotating words with a blinking cursor. Screen readers get the first word; reduced motion shows it statically.

Build fast sites

Make it simple

ClassWhat it does
efx-typedInline element whose text rotates through data-efx-words.
AttributeDefaultValues
data-efx-wordsWords separated by | or ,.
data-efx-speed60Typing speed, ms per character.
data-efx-back30Deleting speed, ms per character.
data-efx-pause1600Hold time per word in ms.
data-efx-looptruefalse = stop on the last word.
data-efx-cursortrueShow blinking cursor.
data-efx-modetypetype · fade · slide (fade/slide swap whole words).

Animated border

border 1.5 KB

Spinning, tracing, glowing or shifting gradient borders for buttons, cards or anything. Optional loading mode driven by clicks.

Spinning border
Glow pulse
Shifting gradient
ClassWhat it does
efx-border-spinRotating conic-gradient ring.
efx-border-traceA short comet segment travelling around the border (loading indicator).
efx-border-glowGradient ring with a pulsing glow.
efx-border-gradientSlowly shifting linear gradient border.
efx-border-wipeBorder draws itself around the edges on hover / keyboard focus (straight edges).
efx-border-pulseExpanding ring pulse radiating from the element (loops).
AttributeDefaultValues
data-efx-colors(Shine primary/accent/secondary)Gradient colors, e.g. #f0f|#0ff|#f0f (end with the first color for a seamless loop).
data-efx-speed0Seconds per cycle; 0 = CSS default (3s).
data-efx-width0Border width in px; 0 = CSS default (2px).
data-efx-loading"" = always animate · click = animate only while loading (after a click) · always.
data-efx-timeout0With loading=click: auto-stop after ms (0 = until efx:done).
CSS variableDefaultControls
--efx-border-colorsprimary, accent, secondaryComma list of gradient colors.
--efx-border-colorvar(--sh-tone, --sh-primary)Single color for trace and glow.
--efx-border-width2pxRing thickness.
--efx-border-speed3sCycle duration.
--efx-border-radiusinheritRing radius (inherits Shine button/card radius).

Confetti

confetti 1.3 KB

Confetti burst from a button or any element, drawn on one shared fixed canvas that exists only while particles are alive. Listens for click, view or efx:done; any element can also dispatch a bubbling efx:confetti event. Reduced motion: a tiny scale pulse instead.

ClassWhat it does
efx-confettiBurst confetti from this element.
AttributeDefaultValues
data-efx-triggerclickclick · view · done (efx:done from border loading, copy, countdown).
data-efx-count80Particles per burst.
data-efx-spread70Fan angle in degrees (centered upward).
data-efx-velocity45Launch speed.
data-efx-gravity1Gravity multiplier.
data-efx-colorsred|#0af|… (default: Shine primary, accent, success, warning, danger).
data-efx-shapessquare|circle|stripsquare · circle · strip, or any registered confetti-shape.
data-efx-origin"x% y%" of the viewport; empty = pointer / element center.

Extend it

KindSignatureWhat it is
confetti-shape(ctx, size, piece) => voidPaint centered on 0,0 (fillStyle set, already translated/rotated); size is in canvas px; call ctx.fill()/fillRect yourself. piece = { x, y, rot, c, shape }.
<script>
window.EffixConfig = { extend(E) {
  E.add('confetti-shape', 'heart', (c, s) => { c.beginPath(); c.moveTo(0, s / 2); c.bezierCurveTo(-s, -s / 6, -s / 3, -s, 0, -s / 4); c.bezierCurveTo(s / 3, -s, s, -s / 6, 0, s / 2); c.fill(); });
} };
</script>
<button class="btn efx-confetti" data-efx-shapes="heart|circle" data-efx-colors="#f43f5e|#fb7185">Love</button>

Ambient backgrounds

ambient 2.7 KB

Animated canvas backgrounds for any section, card or button: twinkling stars, warp-speed starfield, soft drifting orbs (mesh gradient), waves, snow, leaves and bubbles. Pauses off-screen and in hidden tabs; one static frame with reduced motion.

Mesh gradient orbs

Move the pointer: the orbs drift toward it.

Warp

Waves

Snow

Leaves

Bubbles

Stars

Dots

ClassWhat it does
efx-ambientInjects a canvas behind the content (content stays clickable and above). Pick the look with data-efx-mode.
AttributeDefaultValues
data-efx-modestarsstars · warp · orbs · waves · snow · leaves · bubbles · grid (cells light up near the pointer) · flicker (flickering squares) · meteors (diagonal shooting streaks) · dots (fine dot grid that glows near the pointer), or any registered ambient-mode
data-efx-count0Number of particles / orbs / wave layers. 0 = automatic by area and mode.
data-efx-color(theme)One color or a list separated by | (commas outside parentheses also work). Empty = Shine tone/primary.
data-efx-speed1Speed multiplier.
data-efx-opacity1Overall opacity (0–1).
data-efx-interacttrueStars, warp, orbs and grid react to the pointer (fine pointers only). false = ignore the pointer.
CSS variableDefaultControls
--efx-colorShine tone / primaryColor when data-efx-color is empty.

Extend it

KindSignatureWhat it is
ambient-mode{ count(area)->n, spawn(p,S,first), step(p,S)->alive, draw(ctx,p,S), blend?, ptr? }S = { w, h, t, sp, op, px, py, ptr:{x,y,on}, rnd(a,b) }. Feature sets p.c (color), p.i (index), fillStyle/strokeStyle/globalAlpha before draw; step returning false respawns p. blend = globalCompositeOperation; ptr:1 enables pointer tracking.
<script>
window.EffixConfig = { extend(E) {
  E.add('ambient-mode', 'rain', {
    count: a => Math.min(150, a / 6e3 | 0),
    spawn: (p, S, first) => { p.x = S.rnd(0, S.w); p.y = first ? S.rnd(0, S.h) : -20; p.v = S.rnd(6, 12); },
    step: (p, S) => (p.y += p.v * S.sp) < S.h,
    draw: (c, p, S) => { c.lineWidth = 1; c.beginPath(); c.moveTo(p.x, p.y); c.lineTo(p.x, p.y + 10); c.stroke(); },
  });
} };
</script>
<section class="efx-ambient" data-efx-mode="rain" style="min-height:240px;background:#0f172a"></section>

Dot globe

globe 1.2 KB

A lightweight rotating globe made of dots on a canvas: back-facing dots fade, optional pulsing location markers, drag to spin. Pauses off-screen; a static frame with reduced motion. Lazy: starts when near the viewport.

ClassWhat it does
efx-globeHost. Square by default (aspect-ratio 1): set a width or max-width. The canvas fills it.
AttributeDefaultValues
data-efx-dots1200Number of dots on the sphere.
data-efx-speed0.2Auto-rotation in radians per second (0 = still, negative = reverse).
data-efx-markers(none)lat,lon pairs separated by |, e.g. 51.5,-0.12|40.7,-74. Markers pulse while facing you.
data-efx-color(theme)Dot and marker color. Empty = Shine tone/primary.
data-efx-tilt0.3Initial axis tilt in radians.
data-efx-dragtrueDrag with the pointer to rotate.
CSS variableDefaultControls
--efx-colorShine tone / primaryColor when data-efx-color is empty.

Particles

particles 1.8 KB

Drifting canvas particles behind any section, optionally linked by lines and reacting to the pointer. Pauses off-screen and in hidden tabs.

Connected particles

Move the pointer over this area.

Multicolor squares

ClassWhat it does
efx-particlesInjects a canvas behind the content (content stays clickable and above).
AttributeDefaultValues
data-efx-count50Max particles (also capped by area / 14000).
data-efx-color(theme)One color or a list separated by | (commas outside parentheses also work) for multicolor, e.g. rgb(1,2,3)|#f00. Empty = Shine tone/primary.
data-efx-size-min1Smallest radius in px.
data-efx-size-max2.8Largest radius in px.
data-efx-speed100Speed in percent.
data-efx-opacity1Particle opacity (0–1).
data-efx-linksfalseDraw lines between nearby particles.
data-efx-link-distance110Max link length in px.
data-efx-interactrepelnone · repel · attract · connect (pointer joins the network).
data-efx-interact-radius120Pointer influence radius in px.
data-efx-shapecirclecircle · square · triangle · star · heart, a list like circle|star, or any registered particle-shape.
CSS variableDefaultControls
--efx-colorShine tone / primaryParticle color when data-efx-color is empty.

Extend it

KindSignatureWhat it is
particle-shape(ctx2d, size, particle) => voidBuild a path (no beginPath/fill) centered on 0,0; size is the particle radius. Feature translates, fills and uses data-efx-shape="name" or "a|b".
<script>
window.EffixConfig = { extend(E) {
  E.add('particle-shape', 'plus', (ctx, s) => { ctx.rect(-s * .3, -s * 1.2, s * .6, s * 2.4); ctx.rect(-s * 1.2, -s * .3, s * 2.4, s * .6); });
} };
</script>
<div class="efx-particles" data-efx-shape="plus|star" style="min-height:240px"></div>

Cursor trail

trail 1.6 KB

Images, dots, rings or emoji spawn along the pointer path inside an element and fade away. Hover mode shows a floating preview image that follows the pointer over [data-efx-image] items. Nodes are pooled and reused. Fine pointers and motion-OK only.

Move the pointer around here

ClassWhat it does
efx-trailSection that shows the trail / hover preview (becomes position:relative if static).
efx-trail__itemInjected, pooled, aria-hidden trail node.
AttributeDefaultValues
data-efx-imagesa.jpg|b.jpg|c.jpg : images to spawn (random pick).
data-efx-spacing80Pointer distance in px between spawns.
data-efx-life900Lifetime of each item in ms.
data-efx-size140Item size in px (preview width in hover mode).
data-efx-rotate12Random rotation +/- degrees.
data-efx-max12Pool size (items alive at once).
data-efx-shapeWithout images: dot · ring · emoji:✨ · or name[:arg] of any registered trail-shape
data-efx-modetrailtrail · hover (floating preview of the hovered [data-efx-image]).
data-efx-imageOn a child in hover mode: preview image URL.
CSS variableDefaultControls
--efx-colorShine tone/primaryColor for dot and ring shapes.

Extend it

KindSignatureWhat it is
trail-shape(size, arg) => NodeReturn a DOM node placed inside each pooled item (item is size x size, centered; style the node yourself). data-efx-shape="name:arg" passes arg. Built-in: emoji.
<script>
window.EffixConfig = { extend(E) {
  E.add('trail-shape', 'box', (size, arg) => {
    const n = document.createElement('i');
    n.style.cssText = 'width:' + size / 3 + 'px;height:' + size / 3 + 'px;background:' + (arg || 'hotpink') + ';border-radius:20%';
    return n;
  });
} };
</script>
<div class="efx-trail" data-efx-shape="box:tomato" data-efx-size="60" style="min-height:240px"></div>

Custom cursor

cursor 1.1 KB

A ring and/or dot cursor that eases toward the pointer, grows over interactive elements and hides when the pointer leaves the window. Fine pointers and motion-OK only.

Custom cursor zone

A link
ClassWhat it does
efx-cursorOn <body> (page-wide) or any container to enable the custom cursor.
efx-cursor-hoverMark extra elements that should trigger the hover state.
efx-cursor-hideAdded automatically with data-efx-hide-native (cursor:none).
AttributeDefaultValues
data-efx-styleringring · dot · dot-ring
data-efx-size32Ring diameter in px.
data-efx-color(theme)Cursor color.
data-efx-hide-nativefalseHide the native cursor.
data-efx-blendfalsemix-blend-mode: difference.
data-efx-hovera,button,[role=button],input,select,textarea,label,summary,.efx-cursor-hoverSelector that triggers the hover state.
CSS variableDefaultControls
--efx-cursor-colorthemeSet on the injected cursor elements.
--efx-cursor-sizesize optionSet on the injected cursor elements.

Dim siblings

dim 1.2 KB

Hover or focus one item of a list or grid and every sibling dims. Optionally a floating image preview follows the cursor, taken from the item's data-efx-image. Touch taps never dim.

  • Alpha

  • Beta

  • Gamma

  • Delta (no image)

ClassWhat it does
efx-dimList/grid container. Its children (or data-efx-items) dim while one is hovered or focused.
is-hoveredAdded to the active child, handy for an expand/underline style of your own.
AttributeDefaultValues
data-efx-opacity0.35Opacity of the dimmed siblings.
data-efx-blur0Blur in px for dimmed siblings.
data-efx-previewtrueShow a floating image following the cursor when the item has data-efx-image (fine pointers only).
data-efx-itemsCSS selector for the items. Default: direct children.
CSS variableDefaultControls
--efx-dim-opacity0.35Dimmed opacity (also set by data-efx-opacity).
--efx-dim-blur0pxDimmed blur.
--efx-dim-gray0Grayscale amount 0 to 1 for dimmed items.
--efx-dim-size220pxPreview width.

Direction-aware hover

direction 0.9 KB

Detects which edge the pointer entered or left and slides a fill in from that side. Works on buttons, cards, nav items and image tiles; sets data-efx-from so you can build your own transitions.

Card

Enter and leave from different sides.

Another

Keyboard focus fills from the left.

Button

Circle

Floods from where the pointer enters.

ClassWhat it does
efx-directionSets data-efx-from (top | right | bottom | left) and .is-hover; adds the sliding fill overlay.
AttributeDefaultValues
data-efx-filledgeedge = slide from the entry edge · circle = flood as a circle from the exact pointer entry point and retract toward the exit point · false = only set data-efx-from and .is-hover, for custom CSS.
CSS variableDefaultControls
--efx-x / --efx-ypointer %Written in circle mode: the entry/exit point the circle grows from.
--efx-direction-colorShine primary 15%Fill color.
--efx-direction-duration280msSlide duration.

Draggable

draggable 1.8 KB

Drag any element with mouse, touch or pen. Keep it inside bounds, snap it to a grid, and on release spring it home, throw it with inertia (bouncing off the bounds) or leave it. Arrow keys move it when focused.

Spring back

Throw (inertia)

Axis x, 40px grid

ClassWhat it does
efx-draggableMake this element draggable. It moves with the `translate` property (not `transform`), is focusable and gets role="group" + aria-roledescription="draggable".
AttributeDefaultValues
data-efx-axisbothx · y · both
data-efx-boundsparent"parent", a CSS selector of a bounding element, or "none".
data-efx-releasespringspring = snap back to the start · inertia = keep gliding with friction · stay = leave it where dropped.
data-efx-spring170,18Spring "stiffness,damping".
data-efx-friction0.92Inertia: velocity kept per frame (closer to 1 = longer glide).
data-efx-bounce0.5Inertia: speed kept when bouncing off a bound (0 = dead stop).
data-efx-snap0Grid size in px to snap to (0 = off).
data-efx-step10Arrow-key step in px (Shift = ×5; the snap size wins when set).
data-efx-handleSelector inside the element that starts the drag (touch-action:none is set on the handle only).
CSS variableDefaultControls
--efx-colorShine tone/primaryFocus ring color.
EventWhen
efx:dragstartFired once the pointer has moved a few pixels. detail = {x, y}.
efx:dragOn every move (and arrow-key nudge). detail = {x, y} translate offsets.
efx:dragendOn pointer release, before the spring/inertia plays. detail = {x, y}.

Magnetic

magnetic 0.6 KB

Pulls a button or element toward the pointer as it approaches, then springs back. Fine pointers and motion-OK only.

ClassWhat it does
efx-magneticMake this element magnetic.
AttributeDefaultValues
data-efx-strength0.3Fraction of the pointer offset applied.
data-efx-radius120Activation distance (px) beyond the element edge.
data-efx-max24Max displacement in px.
CSS variableDefaultControls
--efx-mx / --efx-myset by JSCurrent offset.

Mouse parallax

mouse 0.8 KB

Layered depth parallax: the container (or children with data-efx-depth) glide against the pointer. Uses the translate/rotate properties, so Shine transforms are untouched. Fine pointers and motion-OK only.

Move the pointer

ClassWhat it does
efx-mouseContainer whose layers follow the pointer.
AttributeDefaultValues
data-efx-strength20Max shift in px at depth 1.
data-efx-scopeselfself = pointer inside the container · page = pointer anywhere in the viewport.
data-efx-invertfalseMove with the pointer instead of against it.
data-efx-rotate0Max rotateZ in degrees per layer.
data-efx-ease0.12Smoothing per frame (0.01 slow – 1 instant).
data-efx-gyrofalseTouch devices: drive the layers from device tilt. Never prompts; on iOS it only works if your page already obtained motion permission.
data-efx-depthOn a child layer: multiplier of strength (e.g. 0.2 far, 1 near, negative = opposite).

Ripple

ripple 0.7 KB

Material-style click ripple for buttons and cards. Enter/Space ripple from the centre. Disabled under reduced motion.

Cards ripple too
ClassWhat it does
efx-rippleAdds position:relative, overflow:hidden and the click ripple.
AttributeDefaultValues
data-efx-color(currentColor 25%)Ripple color.
data-efx-duration600Duration in ms.
data-efx-centerfalseAlways ripple from the centre.
CSS variableDefaultControls
--efx-ripple-colorcurrentColor 25%Ripple color.
--efx-ripple-dur600msDuration.

Spotlight

spotlight 0.7 KB

A radial glow that follows the pointer inside a card or section, optionally lighting the border too. Fine pointers only.

Spotlight

Move the pointer around.

Lit border

Border glows too.

ClassWhat it does
efx-spotlightAdd the pointer-following glow to this element.
efx-spotlight--borderAdded automatically with data-efx-border.
AttributeDefaultValues
data-efx-size240Glow radius in px.
data-efx-color(theme)Glow color. Empty = Shine tone/primary.
data-efx-opacity0.18Glow strength (0–1).
data-efx-borderfalseAlso light the border.
CSS variableDefaultControls
--efx-x / --efx-yset by JSPointer position inside the element.
--efx-colorShine tone / primaryGlow color fallback.

Tilt

tilt 1.0 KB

3D tilt toward the pointer with optional glare. Fine pointers and motion-OK only.

Tilt

Hover me.

With glare

Stronger tilt.

ClassWhat it does
efx-tiltTilt this element toward the pointer.
efx-tilt__glareInjected glare layer (data-efx-glare).
AttributeDefaultValues
data-efx-max10Max rotation in degrees.
data-efx-perspective900Perspective in px.
data-efx-scale1.02Scale while hovered.
data-efx-glarefalseAdd a light glare following the pointer.
data-efx-resettrueEase back to flat when the pointer leaves.
data-efx-gyrofalseTouch devices: tilt with the phone (deviceorientation). Never prompts; on iOS it only works if your page already obtained motion permission.
CSS variableDefaultControls
--efx-rx / --efx-ryset by JSCurrent rotation (read-only in practice).

Beam connectors

beam 1.2 KB

Animated SVG beams that connect elements: perfect for integration diagrams and "how it works" maps. A faint curved path with a glowing segment travelling along it. Re-routes on resize; pauses off-screen; static paths with reduced motion.

Slack
GitHub
Stripe
Hub
Dashboard
ClassWhat it does
efx-beamContainer holding the nodes. Draws an overlay SVG (no pointer events) with one beam per link.
AttributeDefaultValues
data-efx-links(none)Links as from>to pairs separated by |, e.g. #a>#hub|#b>#hub. Selectors are scoped to the container.
data-efx-curvature40Curve height in px (0 = straight line, negative bends downward).
data-efx-speed3Seconds for a beam to travel its path.
data-efx-width2Stroke width in px.
data-efx-color(Shine primary to accent)Solid CSS color. Empty = gradient from --sh-primary to --sh-accent.
data-efx-reversefalseTravel from the second element to the first.
CSS variableDefaultControls
--sh-primary#6366f1Gradient start (Shine token).
--sh-accent#ec4899Gradient end (Shine token).

Shape dividers

divider 2.2 KB

Animated SVG dividers (waves, clouds, mountains, drips…) generated inline and colored to match the neighbouring section.

Wavy section

Dividers drift along the bottom edge.

New shapes

hills drift; the white edge is a custom data-efx-path.

ClassWhat it does
efx-dividerPlaceholder block; JS fills it with an SVG. Shapes: wave, waves, tilt, curve, triangle, arrow, zigzag, clouds, mountains, drips (hangs from the top), steps, spikes, sawtooth, chevron, swoosh, leaves, hills. Or draw your own with data-efx-path.
AttributeDefaultValues
data-efx-shapewavewave · waves · tilt · curve · triangle · arrow · zigzag · clouds · mountains · drips · steps · spikes · sawtooth · chevron · swoosh · leaves · hills, or any registered divider-shape
data-efx-colorFill color; empty = --efx-divider-color or Shine --sh-bg.
data-efx-height80Height in px.
data-efx-flipfalseMirror horizontally.
data-efx-invertfalseMirror vertically (for dividers at the top of a section).
data-efx-animatenonenone · drift (periodic shapes scroll sideways) · layers (3 drifting copies) · float (bob). Non-periodic shapes fall back to float.
data-efx-speed12Seconds per drift loop.
data-efx-pathCustom SVG path data in a 1200x120 viewBox (e.g. "M0,60 C300,0 700,120 1200,40 L1200,120 L0,120 Z"); overrides shape, not periodic (drift falls back to float).
data-efx-positiontop · bottom = absolutely placed on the parent section edge; empty = normal block.
CSS variableDefaultControls
--efx-divider-colorvar(--sh-bg)Fill color (use the next section's background).

Extend it

KindSignatureWhat it is
divider-shape{ periodic: 0|1, layers: [[y0, side, tile(ox) -> "L x,y…"]], ops?: [opacity…] }Each layer is an SVG path in a 1200x120 viewBox: it starts at M0,y0, tile(ox) returns the path segments for one 1200-wide tile starting at x offset ox (periodic shapes must end at the same y they start so tiles join), side b|t = filled below|above. periodic 1 lets animate=drift/layers scroll it.
<script>
window.EffixConfig = { extend(E) {
  E.add('divider-shape', 'saw', { periodic: 1, layers: [[100, 'b', ox => { let d = ''; for (let i = 0; i < 10; i++) d += 'L' + (ox + i * 120 + 100) + ',30L' + (ox + i * 120 + 120) + ',100'; return d; }]] });
} };
</script>
<section style="position:relative;height:160px;background:#4f46e5"><div class="efx-divider" data-efx-shape="saw" data-efx-position="bottom" data-efx-color="#fff"></div></section>

Shape morph

shape 2.0 KB

Morphs one SVG shape into another. Every shape is resampled to N points, the start points are aligned for minimum travel, and the polygon is interpolated. Loop through shapes, morph on hover/focus, or scrub with scroll. Built-ins: blob, circle, star, heart, square (add your own).

ClassWhat it does
efx-shapeOn an <svg> (a path is generated inside, filled with the Shine tone) or directly on a <path> (keeps your own fill/stroke).
AttributeDefaultValues
data-efx-dPipe-separated shapes: registered names (blob|star) or path data "M…|M…". Names use a 0 0 100 100 viewBox (set for you on an <svg> without one).
data-efx-shapesPipe-separated selectors of existing geometry (path, circle, rect…), e.g. "#s1|#s2|#s3". Put the sources in <defs>.
data-efx-toOn a <path>: target path data. Morphs from the path's own d (pipe-separate for more).
data-efx-points64Samples per shape. More = smoother, heavier.
data-efx-triggerlooploop (cycle all shapes) · hover (first -> second on hover/focus) · scroll (progress through the viewport)
data-efx-duration1200Morph time in ms.
data-efx-pause800loop: hold time between morphs in ms.
data-efx-easeease-in-outEasing name (see Effix.add("easing")).
data-efx-targethover: selector of the element that listens (default: the closest link/button, else the shape).
CSS variableDefaultControls
--efx-colorShine tone/primaryFill of the generated path.

Extend it

KindSignatureWhat it is
Effix.add'shape', name, dRegister a named shape: path data in a 0 0 100 100 box. Then use data-efx-d="name|star".
Effix.add('shape', 'bolt', 'M58,4 L20,56 H46 L38,96 L82,40 H54 Z');
Effix.refresh(document.querySelector('.efx-shape'));

Animated feed

feed 0.8 KB

An activity or notification feed: the children of the container appear one at a time and push the others down with a smooth height animation, then loop. Pauses off-screen and in hidden tabs; reduced motion shows the first items statically.

New signup: Ada
Payment received: $49
Deploy finished on main
Comment from Linus
Invoice #1042 sent
New review: 5 stars
ClassWhat it does
efx-feedContainer. Its direct children are the feed items (cards, rows, anything). Add .stack or a flex column for spacing.
AttributeDefaultValues
data-efx-interval1500Milliseconds between new items.
data-efx-max4How many items are visible at once (the oldest leaves when exceeded).
data-efx-looptrueStart over after the last item. false = stop once all have appeared.
data-efx-ordernewestnewest = new items enter at the top · append = enter at the bottom.

Audio visualizer

audio 2.3 KB

Audio-reactive canvas visualizer (bars, wave, circle, scope, dots) for an

Beat
ClassWhat it does
efx-audioThe visualizer box (give it a height). Injects a canvas; may also contain the media element.
efx-audio__canvasInjected canvas (aria-hidden, pointer-events none).
AttributeDefaultValues
data-efx-for(audio/video inside)Selector of the media element, e.g. #song.
data-efx-typebarsbars · wave · circle · scope · dots, or any registered audio-viz.
data-efx-color(Shine chain)Color or list separated by |; empty = --efx-chart-1…4, then Shine tone/primary.
data-efx-count48Number of bars / spokes.
data-efx-gain1Multiplier on the --efx-level value.
CSS variableDefaultControls
--efx-level0Written on the visualizer and on any [data-efx-level-for="#media"] element: smoothed loudness 0–1. e.g. transform: scale(calc(1 + var(--efx-level) * .3)).

Extend it

KindSignatureWhat it is
audio-viz(ctx2d, { freq, time, level, count }, w, h, colors) => voidDraw one frame (canvas is cleared for you). freq/time are Uint8Arrays from the AnalyserNode; level is 0–1; sizes are CSS px.
<script>
window.EffixConfig = { extend(E) {
  E.add('audio-viz', 'pulse', (c, d, w, h, colors) => { c.fillStyle = colors[0]; c.beginPath(); c.arc(w / 2, h / 2, 10 + d.level * h / 2, 0, 6.28); c.fill(); });
} };
</script>
<div class="efx-audio" data-efx-for="#song" data-efx-type="pulse" style="height:160px"></div>

Before / after compare

compare 1.3 KB

Drag a handle to reveal the second image over the first. Keyboard and screen reader friendly via a hidden range input.

Before After
ClassWhat it does
efx-compareContainer with exactly two <img> children: before, then after. Gets .is-dragging while dragging.
AttributeDefaultValues
data-efx-start50Starting position, percent.
data-efx-verticalfalseSplit top/bottom instead of left/right.
data-efx-hoverfalseFollow the mouse without dragging (fine pointers only).
CSS variableDefaultControls
--efx-pos50%Current split position (set by JS).
--efx-handlevar(--sh-bg)Handle line color.

Copy to clipboard

copy 0.6 KB

Copies an element's text (or a literal) to the clipboard, swaps the label and announces it to screen readers.

npm install effix
ClassWhat it does
efx-copyAdd to a button. Gets .is-copied while the done label shows.
AttributeDefaultValues
data-efx-targetCSS selector of the element to copy. Inputs/textareas use their value, others textContent.
data-efx-textLiteral text to copy (wins over target).
data-efx-doneCopied!Label shown after copying.
data-efx-duration1800Ms before the label reverts.

Drag to scroll

drag 0.7 KB

Click-and-drag panning with momentum for any overflowing container, including Shine carousels. Mouse only (touch scrolls natively); clicks after a drag are suppressed and scroll-snap is paused while dragging.

One

Drag me sideways.

Three

Four

Five

ClassWhat it does
efx-dragContainer with overflow: auto/scroll. Gets grab/grabbing cursors and .is-dragging while dragging.
AttributeDefaultValues
data-efx-inertiatrueKeep gliding after release (friction 0.95). Off with reduced motion.
data-efx-axisxx · y · both

Image zoom lens

zoom 0.9 KB

Hover magnifier for images: a round or square lens, or the whole image zooming in place like product pages. Uses an optional large version of the image. Fine pointers only; touch is untouched.

Gradient sample
Gradient sample
ClassWhat it does
efx-zoomWrapper around an <img>. Add data-efx-full="large.jpg" on the img (or wrapper) for a sharper zoom source.
AttributeDefaultValues
data-efx-scale2.5Magnification factor.
data-efx-size160Lens diameter in px (circle and square).
data-efx-shapecirclecircle · square · inner (whole image zooms in place, following the pointer).

Layout animation (FLIP)

layout 2.1 KB

Animates a container's children to their new positions whenever they are added, removed, hidden, reordered or resized. Entering items fade and scale in, leaving items fade out from a clone. Ships a filter / sort helper with aria-pressed buttons and a polite live region ("6 items").

Alpha
design · $19
Bravo
dev · $7
Charlie
design dev · $42
Delta
dev · $12
Echo
design · $28
Foxtrot
dev · $3
ClassWhat it does
efx-layoutContainer whose direct children animate when the layout changes (childList, hidden/class/style changes, resizes). Needs no extra markup.
data-efx-filter="tag" · "*"Button: shows children whose data-efx-tags contain the tag (hidden is toggled). Link it with data-efx-for="#grid" or put it inside the container (in a [data-efx-controls] wrapper).
data-efx-sort="key"Button: sorts children by data-efx-key-<key> (numeric when both are numbers, else text); click again to reverse.
data-efx-tagsOn a child: space-separated tags used by the filter.
AttributeDefaultValues
data-efx-duration400Animation length in ms.
data-efx-easecubic-bezier(.22,1,.36,1)CSS easing string (cubic-bezier, ease-out, linear(…)).
data-efx-scale0.9Scale entering items start from / leaving items shrink to.
data-efx-nounitemWord used in the live count ("6 items").
data-efx-countSelector of your own element to receive the count (it gets aria-live="polite"); otherwise a hidden status node is added after the container.
CSS variableDefaultControls
--efx-colorShine tone/primaryOutline of the pressed filter/sort buttons.

Lazy images

lazyimg 0.5 KB

Blur-up image loading: a tiny placeholder shows first, the full image loads when near the viewport and sharpens in. Works for and background images.

Gradient
ClassWhat it does
efx-lazyimgOn an <img> (data-efx-src / data-efx-srcset) or any element with data-efx-bg.
is-lazy / is-loaded / is-errorState classes set by JS.
AttributeDefaultValues
data-efx-margin300pxHow early to start loading (rootMargin).
data-efx-blur12Blur radius in px of the placeholder.
data-efx-srcFull image URL (img).
data-efx-srcsetFull srcset (img); optional data-efx-sizes.
data-efx-bgFull background image URL (any element).
CSS variableDefaultControls
--efx-blurset by JSPlaceholder blur radius.

Lightbox

lightbox 1.7 KB

Opens linked images in one shared Shine modal with captions, prev/next, counter, arrow keys and touch swipe. Links still work without JS.

One Two Three
ClassWhat it does
efx-lightboxContainer of <a href="full.jpg"><img></a> links (or any element with data-efx-src). Caption: data-efx-caption, img alt, or figcaption.
AttributeDefaultValues
data-efx-looptrueWrap from last to first.
data-efx-captionstrueShow captions.
data-efx-groupContainers sharing the same group value form one gallery.
CSS variableDefaultControls
--efx-lb-bgvar(--sh-surface)Dialog background.

Lyrics & captions

lyrics 2.0 KB

Captions or lyrics synced to an audio/video element: the active line is highlighted and scrolled into view inside its own box, words can fill like karaoke, and clicking a line seeks the media. Cues come from JSON or the media's WebVTT track. Reduced motion: no smooth scrolling, whole active line is lit instead of a progressive fill.

ClassWhat it does
efx-lyricsThe lyrics box (scrolls internally; set a height with --efx-lyrics-height).
efx-lyrics__listInjected <ol> of lines.
efx-lyrics__lineInjected <li>; gets aria-current="true" and .is-active while sung.
efx-lyrics__btnInjected seek button (a <span> when data-efx-seek="false").
efx-lyrics__wordInjected word span in karaoke mode (--p = 0..1 fill).
AttributeDefaultValues
data-efx-for(parent audio/video)Selector of the media element, e.g. #song.
data-efx-cuesJSON [{"t":0,"text":"…","end":2,"words":[{"t":0,"w":"…"}]}]. Alternatives: an inline <script type="application/json"> child, or a captions/subtitles <track> on the media (WebVTT; <00:01.500> stamps give word timing).
data-efx-karaokefalseFill words progressively (background-clip text gradient). Words without timing are spread evenly over the line.
data-efx-scrolltrueAuto-scroll the active line to the middle of the box (pauses 3s after you scroll it yourself).
data-efx-seektrueClicking a line sets media.currentTime.
data-efx-offset0Seconds added to the media time (lyrics early/late).
CSS variableDefaultControls
--efx-lyrics-height16remMax height of the box.
--efx-lyrics-activevar(--sh-primary)Active line color.
--efx-lyrics-fillvar(--sh-primary)Karaoke filled color.
--efx-lyrics-dim45% currentColorKaraoke unfilled color.

Popup triggers

popup 0.7 KB

Auto-opens a Shine modal on a timer, after scrolling, or on exit intent, with frequency capping. Also wires up open/close buttons.

ClassWhat it does
efx-popupAdd to a <dialog class="modal">. Opens with showModal(): Esc, focus trap and backdrop come from the browser.
[data-efx-open="id"]Any element (or a[href="#id"]) that opens the popup manually.
[data-efx-close]Inside the dialog: closes it. Clicking the backdrop closes it too.
AttributeDefaultValues
data-efx-delay-1Seconds before auto-opening. -1 = off.
data-efx-scroll0Open after scrolling this percent of the page. 0 = off.
data-efx-exitfalseOpen on exit intent (pointer leaves the top of the window, desktop only).
data-efx-frequencyalwaysalways · session · days · once.
data-efx-days7With frequency="days": wait this many days before showing again.
data-efx-id(element id)Storage key suffix: efx-popup:<id>.

Pricing toggle

pricing 1.7 KB

Monthly/yearly switch that rolls prices to their new values (odometer digits or a count tween), swaps period text, toggles a "save" badge and announces the change. Radiogroup keyboard support.

Save 20%
$9
per month
Fallback tween: $19.50
ClassWhat it does
efx-pricingContainer of the switch and the prices.
efx-pricing__toggleOptional checkbox instead of buttons: unchecked = first period, checked = second.
AttributeDefaultValues
data-efx-periodsMonthly|YearlyPeriod names, in the order of every "|" list below.
data-efx-start0Index of the initial period.
data-efx-duration600Count tween time in ms (non-odometer prices).

Extend it

KindSignatureWhat it is
Attributes[data-efx-period]Switch buttons (value = period name or index). [data-efx-prices="9|90"] price per period; [data-efx-period-text="per month|per year"]; [data-efx-show-on="Yearly"] shown only for that period.
Eventefx:periodFires on the container with detail {index, period}.

Schedule visibility

schedule 0.8 KB

Shows or hides content by date window, weekday and hours of day (visitor local time). Re-evaluates at the next boundary with one timer, no polling.

Shown outside weekday office hours.
ClassWhat it does
efx-scheduleGets [hidden] and .is-scheduled-off while outside its window. Fires "efx:change" with detail {on}. Tip: add `hidden` in the HTML for mode="show" items to avoid a flash.
AttributeDefaultValues
data-efx-fromStart, e.g. 2026-12-01 or 2026-12-01T09:00 (local time).
data-efx-untilEnd (exclusive), e.g. 2026-12-26T00:00.
data-efx-daysWeekdays, e.g. mon-fri or sat,sun.
data-efx-hoursDaily hours, e.g. 09:00-17:00 (may wrap past midnight).
data-efx-modeshowshow = visible inside the window · hide = visible outside it.

Shimmer / skeleton

shimmer 1.0 KB

Loading shimmer: skeleton blocks, shimmering text and a button shine sweep in pure CSS, plus an optional JS wrapper that hides content until an image/element loads (or a timeout) and then crossfades it in. aria-busy tracks the state; reduced motion gives static gray.

Loading…

Content ready

This card was a skeleton for 2.5 seconds.

ClassWhat it does
efx-shimmerSkeleton block. With data-efx-until / data-efx-for it wraps real content and clears when ready.
efx-shimmer-textShimmering text (gradient sweep clipped to the glyphs).
efx-shimmer-btnButton shine sweep (add to .btn).
efx-skeleton-lineText-line placeholder.
efx-skeleton-circleAvatar placeholder.
efx-skeleton-rectImage/card placeholder.
AttributeDefaultValues
data-efx-untilSelector of image/element to wait for (load/error event; "efx:ready" event also works).
data-efx-for0Ms to wait, or the timeout when combined with until.
CSS variableDefaultControls
--efx-shimmer-basevar(--sh-surface-2)Skeleton base color.
--efx-shimmer-hiderivedSweep highlight color.
--efx-shimmer-duration1.6sSweep time.

Smart video

media 0.8 KB

Videos that play when visible, pause off-screen, optionally play on hover, and only download when near the viewport. Reduced motion: no autoplay, a play control instead.

ClassWhat it does
efx-mediaOn a <video>, or on a container holding videos.
efx-media__playInjected play button (reduced motion, container hosts).
AttributeDefaultValues
data-efx-playviewview = play while visible · hover = play on hover/focus (or add data-efx-hover) · none = lazy src only.
data-efx-threshold0.4Visible fraction (0–1) needed before playing.
data-efx-resetfalseRewind to the start when paused.
data-efx-srcOn the video or a <source>: URL, assigned only when within ~300px of the viewport.

Smooth collapse

collapse 0.7 KB

Animates native

open and close (Shine accordions). Keyboard and name groups keep working; reduced motion toggles instantly.

What is Effix?

A small JS partner for the Shine CSS framework.

Is it accessible?

Native details/summary: keyboard and screen readers work as usual.

Opening one closes the other, animated.

Does it need JS?

No: without JS the accordion toggles natively.

ClassWhat it does
efx-collapseOn a <details>, or a container: every <details> inside is animated.
AttributeDefaultValues
data-efx-duration300Animation time in ms.
data-efx-easingeaseAny CSS easing.

Spinners

spinner 1.2 KB

Pure CSS loaders in seven styles. A tiny script adds role="status" and a visually hidden "Loading" label when missing. With reduced motion they switch to a slow, subtle pulse.

ClassWhat it does
efx-spinnerBase loader (ring). Choose a variant with data-efx-type or a class.
efx-spinner-ring / -dots / -bars / -pulse / -orbit / -wave / -squareVariant classes (alternative to data-efx-type).
AttributeDefaultValues
data-efx-typering · dots · bars · pulse · orbit · wave · square
data-efx-labelLoadingHidden label text for screen readers.
CSS variableDefaultControls
--efx-spinner-size2.5remWidth and height.
--efx-colorShine tone/primarySpinner color.

Toast

toast 1.5 KB

Notification toasts that slide in with a springy nudge, stack per corner, auto-hide with a pause on hover/focus, and close with Shine's .btn-close. Show from a template after a delay, from a trigger button, or ad-hoc via an efx:toast event.

ClassWhat it does
efx-toastHidden template whose content becomes the toast. Needs `hidden`. Styled by Shine .toast.
AttributeDefaultValues
data-efx-show(off)Show automatically after this many ms.
data-efx-positionbottom-righttop|bottom + left|center|right.
data-efx-duration5000Auto-hide ms (0 = sticky). Paused while hovered or focused.
data-efx-toneShine tone (primary, success, danger...).

Extend it

KindSignatureWhat it is
Trigger[data-efx-toast="#id"]Clicking shows the template with that id.
Eventefx:toastdocument.dispatchEvent(new CustomEvent("efx:toast", {detail:{text, tone, duration, position}})). Text is inserted as plain text. Requires at least one .efx-toast on the page.

Page transitions

transition 1.3 KB

Smooth navigation between pages: same-origin links play an exit animation, the next page plays the enter animation. Uses native cross-document View Transitions when available, a JS curtain otherwise. Optional link prefetch on hover.

Add the class to your page root, once per page:

<html class="efx-transition" data-efx-style="curtain">

Clicking same-site links then fades or wipes between pages. Links with target=_blank, modifier keys, #anchors, downloads or data-efx-no-transition are left alone.

Example link (not animated)
ClassWhat it does
efx-transitionPut on <html> or <body> of every page that should animate (use it on all pages, so enter + exit match).
efx-transition__curtainInjected overlay used by the JS fallback.
AttributeDefaultValues
data-efx-stylefadefade · slide-up · curtain · zoom
data-efx-duration400Animation length in ms.
data-efx-prefetchtrueAdd <link rel=prefetch> when an internal link is hovered or focused.
data-efx-no-transitionOn a link (or ancestor): navigate normally, no animation.
CSS variableDefaultControls
--efx-colorShine primaryCurtain color (style "curtain").

Countdown

countdown 1.2 KB

Live countdown to a date, rendered as a cluster of small cards (or one compact line). Pauses while the tab is hidden and fires efx:done at zero.

ClassWhat it does
efx-countdownContainer; renders .efx-countdown__unit > __num + __label.
AttributeDefaultValues
data-efx-toTarget date/time, e.g. 2027-01-31T18:00 (local) or with Z.
data-efx-unitsdhmsSubset of d h m s; larger omitted units roll into the next.
data-efx-labelsDays|Hours|Minutes|SecondsUnit labels separated by |.
data-efx-expiredText shown when finished; empty = keep zeros.
data-efx-padtrueZero-pad hours/minutes/seconds.
data-efx-compactfalseSingle line like "3d 04:05:06".
CSS variableDefaultControls
--efx-countdown-bgvar(--sh-surface-2)Unit card background.

Bar chart

chart-bar 2.7 KB

Vertical or horizontal bars, grouped or stacked. Hover or arrow-key through bars for tooltips, click a legend key to hide a series, click a bar to fire efx:select.

Revenue

Lollipop

Radial

100% stacked

Diverging

Data format
Categories = data-efx-labels, one number per category per series. data-efx-data="12,19,7" (one series) or "3,5|4,1" (several, split by |). JSON: [[3,5],[4,1]] · [{"name":"2025","data":[3,5]},{"name":"2026","data":[4,1]}] · [{"label":"Q1","value":3}]. Also {"labels":[…],"series":[{"name","values"}]}, an inline <script type="application/json">, or a table via data-efx-source (first column = labels, other columns = series). Per-series color: {"name":"A","data":[…],"color":"#f43f5e"}.
ClassWhat it does
efx-chart-barRenders a bar chart from data-efx-data, inline JSON or a table.
AttributeDefaultValues
data-efx-data"12,19,7" · several series "3,5|4,1" · JSON [[3,5],[4,1]] or [{"name":"A","data":[…]}]
data-efx-labelsCategory labels: "Q1|Q2|Q3".
data-efx-namesSeries names: "2025|2026".
data-efx-sourceCSS selector of a Shine table to read (first column = labels).
data-efx-horizontalfalseHorizontal bars.
data-efx-stackedfalseStack series instead of grouping.
data-efx-stylebar<code>lollipop</code> draws a stick and a dot instead of a bar.
data-efx-radialfalseCircular barplot: bars radiate from an inner circle, labels around the ring (works stacked or grouped).
data-efx-normalizefalse100% stacked: every category is scaled to 100% (tooltip shows % and raw value).
data-efx-divergingfalseNegative values extend left/down from a centred zero line; with one series negatives use the danger colour.
data-efx-valuesfalsePrint values on the bars.
data-efx-radius4Bar corner radius.
data-efx-height260Chart height in px (0 = element CSS height).
data-efx-colorsShine tonesSeries colors "#f43f5e|#8b5cf6".
data-efx-prefix / suffixValue formatting, e.g. "$" or "%".
data-efx-compactfalse12.3k style numbers.
data-efx-decimals-1Fixed decimals (-1 = auto).
data-efx-legend / tooltip / animatetrueTurn parts off.
data-efx-backgroundfalseDecorative: fills the element behind its content (no axes/tooltip).
data-efx-titleAccessible name (else aria-label or first heading).
CSS variableDefaultControls
--efx-chart-1 … 7Shine tonesPalette.
--efx-chart-gridborder colorGridlines.
--efx-chart-textmuted textAxis labels.
--efx-chart-bg-opacity.35Opacity in background mode.
EventWhen
efx:selectBar clicked / Enter pressed. detail = { index, label, value, series }.
efx:data (listen)Dispatch on the chart with detail { labels, series } to update it.

Box plot

chart-box 2.4 KB

Box-and-whisker plot from raw samples or precomputed five-number summaries. Hover or arrow-key through boxes for min, Q1, median, Q3, max and outlier count.

Response time by region (ms)

Spread

A box plot as a card background.

Data format
Raw samples per category (quartiles are computed, linear interpolation, whiskers at 1.5×IQR, the rest are outlier dots): {"labels":["A","B"],"series":[{"name":"2026","data":[[3,4,4,5,9],[6,7,7,8,8]]}]} Or precomputed, one object per category: [{"label":"A","min":1,"q1":2,"median":3,"q3":4,"max":5,"outliers":[9]}] Several series are grouped side by side (legend toggles them); labels can also come from data-efx-labels. Inline <script type="application/json"> works too.
ClassWhat it does
efx-chart-boxRenders a box plot from JSON samples or summaries.
AttributeDefaultValues
data-efx-dataJSON: {labels, series:[{name, data:[[samples]…]}]} or [{label,min,q1,median,q3,max,outliers}].
data-efx-labelsCategory labels: "A|B|C".
data-efx-namesSeries names for the legend.
data-efx-horizontalfalseHorizontal boxes.
data-efx-gridtrueGridlines.
data-efx-height260Chart height in px (0 = element CSS height).
data-efx-colorsShine tonesColors "#f43f5e|#8b5cf6".
data-efx-prefix / suffixValue formatting, e.g. "$" or "%".
data-efx-compact / decimals / formatfalse / -1Number formatting (or a registered formatter name).
data-efx-tooltip / animatetrueTurn parts off.
data-efx-backgroundfalseDecorative: fills the element behind its content (no axes/tooltip).
data-efx-titleAccessible name (else aria-label or first heading).
CSS variableDefaultControls
--efx-chart-1 … 7Shine tonesPalette.
--efx-chart-grid / textthemeGridlines and axis labels.
--efx-chart-bg-opacity.35Opacity in background mode.
EventWhen
efx:selectBox clicked / Enter pressed. detail = { index, label, value (median), series }.
efx:data (listen)Dispatch with detail { labels, series } (same shape as data-efx-data) to update.

Bullet chart

chart-bullet 2.3 KB

Stephen Few bullet chart: grayscale qualitative bands, a colored measure bar and a target tick per row. Compact enough for KPI cards; horizontal by default.

Quarterly KPIs

Signups
Uptime %
Goal: 7 of 10
Data format
One row per KPI: [{"label":"Revenue","value":270,"target":300,"ranges":[150,225,300],"max":320}] ranges are ascending upper bounds of the qualitative bands (poor, ok, good); max optional (default = largest number in the row); color optional per row. Or flat: data-efx-data="270,45" data-efx-labels="Revenue|Profit" data-efx-targets="300|50" data-efx-ranges="150,225,300". Each row has its own 0–max scale unless data-efx-shared is set (one common axis).
ClassWhat it does
efx-chart-bulletRenders bullet rows from JSON rows or flat values + targets + ranges.
AttributeDefaultValues
data-efx-dataJSON rows [{label, value, target, ranges:[…], max?}] or "270,45" with labels/targets/ranges.
data-efx-labelsRow labels (flat form): "Revenue|Profit".
data-efx-targetsTargets (flat form): "300|50" (one value = all rows).
data-efx-rangesBand upper bounds for every row: "150,225,300".
data-efx-verticalfalseColumns instead of rows.
data-efx-bar-height18Thickness of each bullet in px (try 10 for a compact list).
data-efx-sharedfalseOne common scale and axis for all rows.
data-efx-valuestruePrint the value next to each row.
data-efx-height220Height in px (vertical only; rows size themselves).
data-efx-colorsShine tonesMeasure bar color.
data-efx-prefix / suffixValue formatting.
data-efx-compact / decimals / formatfalse / -1Number formatting (or a registered formatter name).
data-efx-tooltip / animatetrueTurn parts off.
data-efx-backgroundfalseDecorative: bands and bars fill the element behind its content.
data-efx-titleAccessible name.
CSS variableDefaultControls
--efx-chart-1Shine primaryMeasure bar.
--efx-chart-textmuted textRow labels.
--efx-chart-bg-opacity.35Opacity in background mode.
EventWhen
efx:selectRow clicked / Enter pressed. detail = { index, label, value }.
efx:data (listen)Dispatch with detail as a rows array [{label,value,target,ranges}] (or { labels, series }) to update.

Candlestick chart

chart-candle 2.2 KB

Candlestick or OHLC bars with an optional volume strip. A crosshair tooltip shows open, high, low, close and the period change; many points automatically give thin candles and fewer axis labels.

ACME share price

Market pulse
Data format
One row per period with open, high, low, close and optional volume. data-efx-data='[{"label":"Mon","o":10,"h":14,"l":9,"c":13,"v":900},{"label":"Tue","o":13,"h":15,"l":11,"c":12,"v":700}]' Or series arrays in the order (or named) open, high, low, close, volume, with labels from data-efx-labels: [{"name":"open","data":[10,13]},{"name":"high","data":[14,15]},{"name":"low","data":[9,11]},{"name":"close","data":[13,12]},{"name":"volume","data":[900,700]}] Rows where close ≥ open are drawn green, others red. data-efx-volume adds volume bars. A table via data-efx-source (columns Open, High, Low, Close, Volume) also works.
ClassWhat it does
efx-chart-candleRenders OHLC data as candles or OHLC bars.
AttributeDefaultValues
data-efx-dataJSON [{label,o,h,l,c,v?}] or OHLC(V) series arrays.
data-efx-labelsPeriod labels (series form): "Mon|Tue|Wed".
data-efx-stylecandle<code>candle</code> (body + wick) or <code>ohlc</code> (open/close ticks).
data-efx-volumefalseVolume bars in the bottom 20% of the plot.
data-efx-colorssuccess / dangerOverride as "up|down".
data-efx-prefix / suffixValue formatting, e.g. "$".
data-efx-compact / decimals / formatNumber formatting.
data-efx-height260Chart height in px.
data-efx-tooltip / animate / gridtrueTurn parts off.
data-efx-backgroundfalseDecorative: fills the element behind its content.
data-efx-titleAccessible name.
CSS variableDefaultControls
--sh-success / --sh-dangerShine tonesUp and down colors.
--efx-chart-grid / --efx-chart-textGridlines and axis text.
EventWhen
efx:selectCandle clicked / Enter pressed. detail = { index, label, value (close) }.
efx:data (listen)Dispatch with detail as the rows array, {rows:[…]}, or { labels, series }.

Combo chart

chart-combo 2.4 KB

Bars and lines on one plot, with an optional second y-axis on the right. A crosshair tooltip lists every series at the hovered x; arrow keys step through categories and legend keys toggle series.

Revenue and margin

Data format
Categories = data-efx-labels; each series has numbers per category plus a type and axis. [{"name":"Revenue","data":[40,52,48],"type":"bar"},{"name":"Margin %","data":[22,31,27],"type":"line","axis":"right"}] type: "bar" (default for the first series) or "line"; axis: "left" (default) or "right". Plain data works too: data-efx-data="40,52,48|22,31,27" data-efx-names="Revenue|Margin %" with data-efx-types="bar|line" and data-efx-axes="left|right". Tables via data-efx-source use the attributes.
ClassWhat it does
efx-chart-comboRenders bars and lines from data-efx-data (per-series type and axis) or inline JSON.
AttributeDefaultValues
data-efx-dataJSON [{"name","data","type":"bar|line","axis":"left|right"}] or "40,52|22,31".
data-efx-labelsCategory labels: "Jan|Feb|Mar".
data-efx-namesSeries names: "Revenue|Margin %".
data-efx-typesPer-series fallback: "bar|line" (first series bar, others line when omitted).
data-efx-axesPer-series fallback: "left|right".
data-efx-smoothtrueSmooth (monotone) lines.
data-efx-dotstrueDots on line points (false = only on hover).
data-efx-areafalseGradient fill under the lines.
data-efx-radius4Bar corner radius.
data-efx-prefix / suffixLeft axis and tooltip value formatting, e.g. "$" / "k".
data-efx-prefix2 / suffix2Right axis formatting, e.g. "%".
data-efx-height260Chart height in px.
data-efx-colorsShine tonesSeries colors "#f43f5e|#8b5cf6".
data-efx-legend / tooltip / animate / gridtrueTurn parts off.
data-efx-backgroundfalseDecorative: fills the element behind its content.
data-efx-titleAccessible name.
CSS variableDefaultControls
--efx-chart-1 … 7Shine tonesPalette.
EventWhen
efx:selectColumn clicked / Enter pressed. detail = { index, label, value, series }.
efx:data (listen)Dispatch with detail { labels, series:[{name, values, type, axis}] } to update.

Flow chart

chart-flow 2.5 KB

Lightweight Sankey-style flow for funnels and user journeys. Hover a ribbon to see A → B: value (x% of A) and light up the two nodes it joins; hover a node to light up its links.

Signup funnel

Journey

A flow as a card background.

Data format
A graph of nodes and weighted links (Sankey). Link source/target are node indexes or names. data-efx-data='{"nodes":[{"name":"Visit"},{"name":"Signup"},{"name":"Paid"}], "links":[{"source":0,"target":1,"value":120},{"source":1,"target":2,"value":45}]}' Names used only in links ("source":"Visit") create nodes automatically. Links need value > 0. Can also live in an inline <script type="application/json">; update with efx:data and the same object.
ClassWhat it does
efx-chart-flowRenders a flow diagram from { nodes, links } JSON.
AttributeDefaultValues
data-efx-dataJSON {"nodes":[{"name":"Visit"},…],"links":[{"source":0,"target":1,"value":120}]}. source/target may be indexes or node names. Or put the JSON in an inline <script type="application/json">.
data-efx-node-width12Node bar width in px.
data-efx-node-pad12Vertical gap between nodes in a column.
data-efx-alignjustify"justify" pushes end nodes to the last column, "left" keeps them where they are.
data-efx-colorsShine tonesNode colors (ribbons take their source node color).
data-efx-height260Chart height in px.
data-efx-prefix / suffix / compact / decimalsValue formatting.
data-efx-tooltip / animatetrueTurn parts off.
data-efx-backgroundfalseDecorative: fills the element behind its content (no labels).
data-efx-titleAccessible name.
CSS variableDefaultControls
--efx-chart-1 … 7Shine tonesPalette.
--efx-chart-bg-opacity.35Opacity in background mode.
EventWhen
efx:selectLink or node clicked / Enter pressed. detail = { index, label, value }.
efx:data (listen)Dispatch with detail { nodes, links } to update.

Funnel chart

chart-funnel 3.7 KB

Conversion funnel with smooth curved, straight, centered-bar or pyramid stages, per-stage and step-to-step conversion, drop-off rates, and a compare mode for two series. Hover for value, % of total, % of previous step and drop count; click a legend key to hide a stage.

Signup funnel

Funnel as a card background

Decorative mode fills the whole card.

Data format
Stages top to bottom = data-efx-labels, one number per stage (usually decreasing). data-efx-data="1200,780,420,180" data-efx-labels="Visits|Signups|Trials|Paid". JSON: [{"label":"Visits","value":1200},{"label":"Signups","value":780}]. Two series compare two funnels (data-efx-compare="mirror|ghost"): "1200,780,420|1000,600,300" or [{"name":"2025","data":[…]},{"name":"2026","data":[…]}].
ClassWhat it does
efx-chart-funnelRenders a funnel from data-efx-data (first series) and data-efx-labels (stage names).
AttributeDefaultValues
data-efx-data"1200,780,420,180" · two series "1200,780|900,700" compare mode · JSON or a table via data-efx-source.
data-efx-labelsStage names: "Visits|Signups|Trials|Paid".
data-efx-stylecurved<code>curved</code> smooth trapezoid stack · <code>straight</code> · <code>bars</code> centered bars with drop-off connectors · <code>pyramid</code>.
data-efx-horizontalfalseFlow left to right.
data-efx-neck0.25Bottom width ratio for curved/straight. 0 = widths proportional to each value.
data-efx-gap4Pixels between stages.
data-efx-conversiontrueShow % of first stage and the "−32%" drop-off between stages.
data-efx-showinsideStage labels: <code>inside</code> (auto-moves outside when too narrow) · <code>side</code> · <code>none</code>. (Not named "labels": that is the stage names.)
data-efx-dynamictrueStage height proportional to value (false = equal heights).
data-efx-comparemirrorWith 2+ series: <code>mirror</code> halves side by side · <code>ghost</code> series 2 as an outline behind series 1.
data-efx-height320Chart height in px (0 = element CSS height).
data-efx-colorsShine tonesColors "#f43f5e|#8b5cf6" (per stage / slice / series).
data-efx-prefix / suffixValue formatting, e.g. "$" or "%".
data-efx-compactfalse12.3k style numbers.
data-efx-decimals-1Fixed decimals (-1 = auto).
data-efx-tooltip / animatetrueTurn parts off.
data-efx-backgroundfalseDecorative: fills the element behind its content (no labels/tooltip).
data-efx-titleAccessible name (else aria-label or first heading).
CSS variableDefaultControls
--efx-chart-1 … 7Shine tonesPalette.
--efx-chart-textmuted textSecondary labels and drop-off rates.
EventWhen
efx:selectStage clicked / Enter pressed. detail = { index, label, value, series }.
efx:data (listen)Dispatch on the chart with detail { labels, series } to update it.

Gauge & ring

chart-gauge 2.3 KB

A 240° gauge (optional needle and target marker), a full progress ring, or concentric radial bars. Sweeps in on entry. Scales down into a badge, button or stat card.

Sprint progress
78% complete
Data format
A single value, within data-efx-min / data-efx-max (default 0–100). data-efx-value="72" (gauge or ring) · or data-efx-data="72"; optional data-efx-label="Uptime", data-efx-target="90". Radial type (data-efx-type="radial"): one ring per value, names from labels: data-efx-data="80,60,35" data-efx-labels="Move|Exercise|Stand" or JSON [{"label":"Move","value":80}]. Live update: dispatch efx:data with detail: { value: 64 }.
ClassWhat it does
efx-chart-gaugeRenders a gauge from data-efx-value (or the first data value).
AttributeDefaultValues
data-efx-typegauge<code>gauge</code> 240° arc · <code>ring</code> full circle · <code>radial</code> one concentric ring per label.
data-efx-valuefirst data valueCurrent value.
data-efx-min / max0 / 100Scale.
data-efx-thick0.18Arc thickness as a ratio of the radius.
data-efx-needlefalseShow a needle (gauge only).
data-efx-targetDraw a target tick at this value.
data-efx-labelCaption under the value.
data-efx-data / labelsFor radial: "80,60,35" and "Move|Exercise|Stand".
data-efx-height320Chart height in px (0 = element CSS height).
data-efx-colorsShine tonesColors "#f43f5e|#8b5cf6" (per stage / slice / series).
data-efx-prefix / suffixValue formatting, e.g. "$" or "%".
data-efx-compactfalse12.3k style numbers.
data-efx-decimals-1Fixed decimals (-1 = auto).
data-efx-tooltip / animatetrueTurn parts off.
data-efx-backgroundfalseDecorative: fills the element behind its content (no labels/tooltip).
data-efx-titleAccessible name (else aria-label or first heading).
CSS variableDefaultControls
--efx-chart-1 … 7Shine tonesArc colors (first = gauge/ring).
EventWhen
efx:selectArc clicked. detail = { index, label, value }.
efx:data (listen)Dispatch with detail { labels, series } to update.

Heatmap

chart-heatmap 2.3 KB

A grid heatmap (labels = columns, series = rows) or a GitHub-style calendar of weeks × 7 days. Color intensity is an opacity ramp of the first palette color, or a two-color diverging scale. Hover or arrow through the cells.

Activity by hour

Contributions

Net change

Diverging scale behind a card

Data format
Grid: labels = columns, each series = a row of numbers (null = empty cell). data-efx-data="[[1,4,2],[3,0,5]]" data-efx-labels="A|B|C" data-efx-names="Row 1|Row 2" or [{"name":"Mon","data":[1,4,2]}], or a table via data-efx-source. Calendar (data-efx-calendar): day values for up to the last 53 weeks: [{"date":"2026-01-03","value":4},{"date":"2026-01-04","value":1}] (ISO YYYY-MM-DD).
ClassWhat it does
efx-chart-heatmapRenders a heatmap from data-efx-data, inline JSON or a table.
AttributeDefaultValues
data-efx-dataGrid: "1,4,2|3,0,5" or JSON [[1,4,2],[3,0,5]]. Calendar: JSON [{"date":"2026-01-03","value":4}].
data-efx-labels / namesGrid column labels "Mon|Tue" / row names "Morning|Evening".
data-efx-sourceCSS selector of a Shine table to read (first column = labels).
data-efx-calendarfalseCalendar mode: weeks as columns, 7 rows, month and weekday labels.
data-efx-scheme"" = single color ramp · "diverging" = colors[0] for positive, danger (or colors[1]) for negative.
data-efx-gap2Space between cells in px.
data-efx-radius2Cell corner radius.
data-efx-heightautopx. Default: 30px per row (grid) or square cells (calendar, max 20px).
data-efx-colorsShine tonesRamp color, or "#positive|#negative" for diverging.
data-efx-prefix / suffix / compact / decimalsTooltip value formatting.
data-efx-tooltip / animatetrueTurn parts off.
data-efx-backgroundfalseDecorative: cells stretch edge to edge behind the element content.
data-efx-titleAccessible name (else aria-label or first heading).
CSS variableDefaultControls
--efx-chart-1 … 7Shine tonesPalette.
--efx-chart-textmutedAxis text and empty cells.
EventWhen
efx:selectCell clicked / Enter pressed. detail = { index, label, value, series }.
efx:data (listen)Grid: detail { labels, series }. Calendar: detail [{date,value}].

Histogram

chart-histogram 1.7 KB

Auto-binned histogram of raw values with touching bars and an optional normal-curve overlay. Tooltip shows the bin range and count.

Page load time (s)

Distribution

A histogram as a card background.

Data format
Raw values, binned for you: data-efx-data="1.2,3.4,2.2,5.1,3.3" (or JSON [1.2,3.4,…], a table column via data-efx-source). Bins: Sturges' rule by default, data-efx-bins="12" for an exact count between min and max, or data-efx-step="5" for a fixed bin width. Bins are half-open [a, b), the last one is closed. Add data-efx-curve to overlay a normal curve fitted to the data. Live update: efx:data with {series:[{values:[…]}]}.
ClassWhat it does
efx-chart-histogramBins the values and renders a histogram.
AttributeDefaultValues
data-efx-data"1.2,3.4,2.2,…" or JSON [1.2,3.4,…].
data-efx-bins0Exact number of bins (0 = Sturges).
data-efx-step0Fixed bin width (wins over bins).
data-efx-curvefalseOverlay a fitted normal curve.
data-efx-gridtrueGridlines.
data-efx-height260Chart height in px (0 = element CSS height).
data-efx-colorsShine tonesColors "#f43f5e|#8b5cf6".
data-efx-prefix / suffixValue formatting, e.g. "$" or "%".
data-efx-compact / decimals / formatfalse / -1Number formatting (or a registered formatter name).
data-efx-tooltip / animatetrueTurn parts off.
data-efx-backgroundfalseDecorative: fills the element behind its content (no axes/tooltip).
data-efx-titleAccessible name (else aria-label or first heading).
CSS variableDefaultControls
--efx-chart-1 … 2Shine tonesBars (1) and curve (2).
--efx-chart-grid / textthemeGridlines and axis labels.
--efx-chart-bg-opacity.35Opacity in background mode.
EventWhen
efx:selectBin clicked / Enter pressed. detail = { index, label: "[a, b)", value: count }.
efx:data (listen)Dispatch with detail { series:[{values}] } to update.

Line chart

chart-line 2.3 KB

Multi-series lines with optional gradient area or stacked area. A crosshair snaps to the nearest point and the tooltip lists every visible series at that x. Arrow keys step through x positions, legend keys toggle series.

Visitors

Revenue

$34k this week

Listening by genre

Data format
Same shapes as the bar chart: one value per label per series. data-efx-data="3,5,4,8" · "3,5,4|2,4,6" (two series) · JSON [[3,5],[4,1]]. Named series: [{"name":"Visits","data":[3,5,4]},{"name":"Signups","data":[1,2,2]}]. Labels: data-efx-labels="Mon|Tue|Wed" or {"labels":[…],"series":[…]}; a table via data-efx-source also works. data-efx-stacked stacks series (areas); values are plain numbers (no dates).
ClassWhat it does
efx-chart-lineRenders a line / area chart from data-efx-data, inline JSON or a table.
AttributeDefaultValues
data-efx-data"3,5,4" · several series "3,5|4,1" · JSON [[3,5],[4,1]] or [{"name":"A","data":[…]}]
data-efx-labelsX labels: "Mon|Tue|Wed".
data-efx-namesSeries names: "2025|2026".
data-efx-sourceCSS selector of a Shine table to read (first column = labels).
data-efx-areafalseGradient fill under each line (35% → 0 of the series color).
data-efx-stackedfalseStacked area (implies area).
data-efx-streamfalseStreamgraph: stacked areas around a centred wiggle baseline (no y axis), smooth. Tooltip still shows real values.
data-efx-smoothtrueMonotone curve; false = straight segments.
data-efx-dotstrueAlways-visible dots; false shows them only under the crosshair.
data-efx-gridtrueHorizontal gridlines.
data-efx-min(auto)Y axis minimum; empty = automatic.
data-efx-height260Chart height in px (0 = element CSS height).
data-efx-colorsShine tonesSeries colors "#f43f5e|#8b5cf6".
data-efx-prefix / suffixValue formatting, e.g. "$" or "%".
data-efx-compact / decimalsfalse / -112.3k style numbers / fixed decimals.
data-efx-legend / tooltip / animatetrueTurn parts off.
data-efx-backgroundfalseDecorative: fills the element behind its content (lines/areas only).
data-efx-titleAccessible name (else aria-label or first heading).
CSS variableDefaultControls
--efx-chart-1 … 7Shine tonesPalette.
--efx-chart-grid / --efx-chart-textborder / mutedGridlines and axis text.
EventWhen
efx:selectPoint clicked / Enter pressed. detail = { index, label, value, series }.
efx:data (listen)Dispatch on the chart with detail { labels, series } to update it.

Pie & donut chart

chart-pie 2.6 KB

Pie, donut or semicircle with outside labels and leader lines. Slices pull out on hover and the donut hole shows the hovered slice. Click a legend key to hide a slice.

Traffic sources

Data format
One slice per label, from the first series only; zero and negative values are skipped. data-efx-data="40,30,20,10" data-efx-labels="A|B|C|D". JSON: [{"label":"Organic","value":4200},{"label":"Direct","value":2800}] or {"labels":["A","B"],"series":[{"values":[40,30]}]}. A table via data-efx-source (first column = slice names, second = values) also works. Slice colors: data-efx-colors="#f43f5e|#8b5cf6" (one per slice).
ClassWhat it does
efx-chart-pieRenders a pie/donut from data-efx-data (first series) and data-efx-labels.
AttributeDefaultValues
data-efx-data"40,30,20,10" · JSON · or a table via data-efx-source.
data-efx-labelsSlice names: "A|B|C|D".
data-efx-donut0.6Inner radius ratio (0 = full pie).
data-efx-pad0.01Gap between slices in radians.
data-efx-sortfalseLargest slice first.
data-efx-centerText in the donut hole. <code>{total}</code> = formatted total. Empty shows the total with caption "Total".
data-efx-showautoLabels: <code>auto</code> outside with leader lines when there is room · <code>percent</code> inside slices · <code>none</code>.
data-efx-halffalseSemicircle.
data-efx-rosefalsePolar-area (Nightingale) rose: equal angles, radius proportional to √value.
data-efx-legendtrueLegend keys toggle slices.
data-efx-height320Chart height in px (0 = element CSS height).
data-efx-colorsShine tonesColors "#f43f5e|#8b5cf6" (per stage / slice / series).
data-efx-prefix / suffixValue formatting, e.g. "$" or "%".
data-efx-compactfalse12.3k style numbers.
data-efx-decimals-1Fixed decimals (-1 = auto).
data-efx-tooltip / animatetrueTurn parts off.
data-efx-backgroundfalseDecorative: fills the element behind its content (no labels/tooltip).
data-efx-titleAccessible name (else aria-label or first heading).
CSS variableDefaultControls
--efx-chart-1 … 7Shine tonesPalette.
EventWhen
efx:selectSlice clicked / Enter pressed. detail = { index, label, value }.
efx:data (listen)Dispatch on the chart with detail { labels, series } to update it.

Progress bars

chart-progress 1.6 KB

Compact goal bars for KPI lists: label on the left, value on the right, a rounded track with an animated fill and an optional target tick. Hover or arrow-key through rows for a tooltip.

Q4 goals

Onboarding

Progress bars as a card background.

Data format
Rows = labels; the first series = current values, an optional second series = targets (100% when absent). data-efx-labels="Signups|Revenue" data-efx-data="820,64|1000,80" (values | targets). JSON: [{"name":"Value","data":[820,64]},{"name":"Target","data":[1000,80]}] or [{"label":"Signups","value":820}]. data-efx-max sets a common scale when there are no targets; a table via data-efx-source also works.
ClassWhat it does
efx-chart-progressRenders one progress bar per label.
AttributeDefaultValues
data-efx-dataValues "820,64,45" or two series "820,64|1000,80" (second series = targets). JSON works too.
data-efx-labelsRow labels: "Signups|Revenue|NPS".
data-efx-sourceCSS selector of a Shine table (column 1 = labels, 2 = values, 3 = targets).
data-efx-maxautoCommon scale for every row. Auto: each row with a target scales to max(target, value); otherwise the largest value.
data-efx-valuestrueShow "value / target" on the right.
data-efx-percenttrueShow the percentage (value / target, else value / scale).
data-efx-thick10Bar thickness in px.
data-efx-radius999Bar corner radius (999 = pill).
data-efx-colorsShine tonesCycled per row; give one color to use it everywhere.
data-efx-heightautoDefaults to a height that fits all rows.
data-efx-prefix / suffix / compact / decimalsValue formatting.
data-efx-tooltip / animatetrueTurn parts off.
data-efx-backgroundfalseDecorative: bars fill the element behind its content.
data-efx-titleAccessible name.
CSS variableDefaultControls
--efx-chart-1 … 7Shine tonesPalette.
--sh-surface-2ShineTrack color.
EventWhen
efx:selectRow clicked / Enter pressed. detail = { index, label, value }.
efx:data (listen)Dispatch with detail { labels, series } to update.

Radar chart

chart-radar 2.0 KB

Radar / spider chart: one polygon per series, one axis per label. Hover vertices for values, click a legend key to hide a series.

Skills

Radar as a background

Data format
Labels = the axes (3 or more), each series = one polygon, one number per axis, scaled to data-efx-max (default: nice max of the data). data-efx-data="[[8,6,7,5,9],[5,8,4,7,6]]" data-efx-names="A|B" data-efx-labels="Speed|Power|Range|Cost|Style" JSON: [{"name":"A","data":[8,6,7,5,9]},{"name":"B","data":[5,8,4,7,6]}]. A single series can be "8,6,7,5,9"; a table via data-efx-source also works.
ClassWhat it does
efx-chart-radarRenders a radar chart (needs 3+ labels).
AttributeDefaultValues
data-efx-data"8,6,7,5,9" · several series "8,6,7,5,9|5,8,4,7,6" · JSON.
data-efx-labelsAxis names: "Speed|Power|Range|Cost|Style".
data-efx-namesSeries names: "A|B".
data-efx-levels4Number of grid rings.
data-efx-areatrueFill the polygons.
data-efx-dotstrueShow vertex dots (hover still works when off).
data-efx-maxautoValue at the outer ring.
data-efx-height320Chart height in px (0 = element CSS height).
data-efx-colorsShine tonesColors "#f43f5e|#8b5cf6" (per stage / slice / series).
data-efx-prefix / suffixValue formatting, e.g. "$" or "%".
data-efx-compactfalse12.3k style numbers.
data-efx-decimals-1Fixed decimals (-1 = auto).
data-efx-tooltip / animatetrueTurn parts off.
data-efx-backgroundfalseDecorative: fills the element behind its content (no labels/tooltip).
data-efx-titleAccessible name (else aria-label or first heading).
CSS variableDefaultControls
--efx-chart-1 … 7Shine tonesSeries colors.
--efx-chart-gridborder colorRings and axes.
EventWhen
efx:selectVertex clicked / Enter pressed. detail = { index, label, value, series }.
efx:data (listen)Dispatch with detail { labels, series } to update.

Scatter chart

chart-scatter 2.2 KB

Scatter and bubble plots on two linear axes. Hover (or arrow through, left to right) for a tooltip with x, y and size; click a legend key to hide a series.

Price vs rating

Customers

Clusters by size

Unemployment vs inflation, 2015-2024

Data format
Points are {x, y} objects; add r (size, with data-efx-bubble) and label if wanted. data-efx-data='[{"x":1,"y":4},{"x":3,"y":7,"r":5,"label":"A"}]' Several series: [[{"x":1,"y":4}],[{"x":2,"y":5}]] or [{"name":"Plan A","points":[{"x":1,"y":4}]}]. Also {"series":[…]} or an inline <script type="application/json">. Axis titles: data-efx-x-label / data-efx-y-label.
ClassWhat it does
efx-chart-scatterRenders a scatter / bubble chart from data-efx-data or inline JSON points.
AttributeDefaultValues
data-efx-dataJSON points [{"x":1,"y":4,"r":3,"label":"A"}] · several series [[{…}],[{…}]] or [{"name":"A","points":[…]}].
data-efx-namesSeries names: "2025|2026".
data-efx-x-label / y-labelAxis titles (also used in the tooltip).
data-efx-connectedfalseJoin each series' points in data order with a line and an arrow at the end (trajectories, paths over time).
data-efx-bubblefalseSize points by r (radius scales with the square root, up to 24px).
data-efx-height260Chart height in px (0 = element CSS height).
data-efx-colorsShine tonesSeries colors "#f43f5e|#8b5cf6".
data-efx-prefix / suffix / compact / decimalsFormatting for y values and y ticks.
data-efx-legend / tooltip / animatetrueTurn parts off.
data-efx-backgroundfalseDecorative: fills the element behind its content.
data-efx-titleAccessible name (else aria-label or first heading).
CSS variableDefaultControls
--efx-chart-1 … 7Shine tonesPalette.
--efx-chart-grid / --efx-chart-textborder / mutedGridlines and axis text.
EventWhen
efx:selectPoint clicked / Enter pressed. detail = { index, label, value (y), series }.
efx:data (listen)Dispatch with detail { series: [{ name, points: [{x,y,r?,label?}] }] } to update.

Sparkline

chart-spark 1.9 KB

A tiny chart for use inside text, badges, buttons and stat cards, or as a card background. Inline elements become about 6em wide and 1.2em tall and sit on the text baseline. Hover for the nearest value.

Signups 1,284 and churn are both improving.

MRR
$48.2k
Daily results
Live
15 online

Data format
A short list of numbers (first series), drawn as data-efx-type="line|bar|win-loss". data-efx-data="3,5,4,8,6,9" or JSON [3,5,4,8,6,9] · [{"label":"Mon","value":3}]. Labels (optional, used by the tooltip): data-efx-labels="Mon|Tue|Wed". Works on any inline element (<span>, badge, button, stat card) or as data-efx-background.
ClassWhat it does
efx-chart-sparkRenders a sparkline (line, bar or win-loss) from data-efx-data.
AttributeDefaultValues
data-efx-data"3,5,4,8" (first series only) · JSON [3,5,4].
data-efx-labelsTooltip labels: "Mon|Tue|Wed" (default 1, 2, 3…).
data-efx-typelineline · bar · win-loss (positive values up, negative down).
data-efx-areatrueGradient fill under the line (type line).
data-efx-lasttrueDot on the last point (type line).
data-efx-smoothtrueMonotone curve (type line).
data-efx-height40 / 1.2emHeight in px; inline elements default to 1.2em, others to 40.
data-efx-colorsShine tonesLine/bar color; win-loss uses "#win|#loss" (default success / danger).
data-efx-prefix / suffix / compact / decimalsTooltip value formatting.
data-efx-legendfalseLegend (off by default).
data-efx-tooltip / animatetrueTurn parts off.
data-efx-backgroundfalseDecorative: fills the element behind its content.
data-efx-titleAccessible name (else aria-label or first heading).
CSS variableDefaultControls
--efx-chart-1 … 7Shine tonesPalette.
--efx-chart-bg-opacity.35Opacity in background mode.
EventWhen
efx:selectPoint clicked / Enter pressed. detail = { index, label, value }.
efx:data (listen)Dispatch with detail { series: [{ values }] } to update.

Sunburst chart

chart-sunburst 2.8 KB

Radial hierarchy: one ring per depth, arc angle = value. Hover highlights the ancestor path and shows it in the center, click zooms into a branch, click the center to go up. Arrow keys and Enter work too.

Budget by team

Disk usage

Storage

A sunburst as a card background.

Data format
A tree: {"name":"All","children":[{"name":"EU","children":[{"name":"FR","value":4},{"name":"DE","value":7}]},{"name":"US","value":12}]} Leaves carry value; a parent's value is the sum of its children. A bare array is treated as the children of an unnamed root. Colors follow the top-level branches (deeper rings are lighter). Click an arc to zoom into it, click the center to go back up. Inline <script type="application/json"> works too; live update with efx:data and a tree as detail.
ClassWhat it does
efx-chart-sunburstRenders a sunburst from a JSON tree.
AttributeDefaultValues
data-efx-dataJSON tree {name, value?, children:[…]}.
data-efx-depth4Rings shown at once (zooming reveals deeper levels).
data-efx-captionstruePrint names on arcs that are big enough.
data-efx-height320Chart height in px.
data-efx-colorsShine tonesOne color per top-level branch.
data-efx-prefix / suffixValue formatting.
data-efx-compact / decimals / formatfalse / -1Number formatting (or a registered formatter name).
data-efx-tooltip / animatetrueTurn parts off.
data-efx-backgroundfalseDecorative: a quiet sunburst behind the element's content.
data-efx-titleAccessible name.
CSS variableDefaultControls
--efx-chart-1 … 7Shine tonesBranch colors.
--efx-chart-bg-opacity.35Opacity in background mode.
EventWhen
efx:selectArc clicked / Enter pressed (index -1 = center, going up). detail = { index, label, value }. Zooming happens on the same click.
efx:data (listen)Dispatch with a tree as detail to replace the data and reset the zoom.

Timeline / Gantt chart

chart-timeline 2.8 KB

Gantt-style timeline: one row per item with optional group lanes, a date axis that picks day, week, month or year ticks, a Today marker and progress fill inside bars.

Launch plan

Sprint view
Data format
One object per bar: label, start, end (ISO dates "2026-01-05" or plain numbers), plus optional group, color, progress (0–1 or 0–100). data-efx-data='[{"label":"Design","start":"2026-01-05","end":"2026-02-01","group":"Phase 1","progress":0.6}, {"label":"Build","start":"2026-02-01","end":"2026-03-15","group":"Phase 2","color":"#8b5cf6"}]' Rows sharing a group are listed together under a group heading and share a color. Also accepts {"rows":[…]} or an inline <script type="application/json">. Dates give a day/week/month/year axis and a Today marker; numbers give a numeric axis.
ClassWhat it does
efx-chart-timelineRenders rows of {label, start, end} as a Gantt chart.
AttributeDefaultValues
data-efx-dataJSON [{label, start, end, group?, color?, progress?}] (dates or numbers).
data-efx-todaytrueMarker for the current date when it falls inside the range (dates only).
data-efx-radius4Bar corner radius.
data-efx-colorsShine tonesGroup colors "#f43f5e|#8b5cf6" (a row's own color wins).
data-efx-prefix / suffix / formatFormatting for numeric axes and durations.
data-efx-tooltip / animate / gridtrueTurn parts off.
data-efx-backgroundfalseDecorative: bars only, filling the element behind its content.
data-efx-titleAccessible name.
CSS variableDefaultControls
--efx-chart-1 … 7Shine tonesGroup palette (Today marker uses the 6th).
EventWhen
efx:selectRow clicked / Enter pressed. detail = { index, label, value (duration) }.
efx:data (listen)Dispatch with detail as the rows array or {rows:[…]} to update.

Treemap chart

chart-treemap 2.0 KB

Squarified treemap: tile area is proportional to value. Hover or arrow-key through tiles for a tooltip with share, click one to fire efx:select. Give it a single color in data-efx-colors for a one-hue ramp by rank.

Spend by category

Portfolio

A treemap as a card background.

Data format
One rectangle per label; area = value. First series only; zero and negative values are skipped. data-efx-data="40,25,15,10" data-efx-labels="A|B|C|D" JSON: [{"label":"Cloud","value":40},{"label":"Ads","value":25}] or {"labels":[…],"series":[{"values":[…]}]}. A table via data-efx-source also works. One data-efx-colors value makes a shaded ramp of it; several = one color per tile.
ClassWhat it does
efx-chart-treemapRenders a treemap from labels and the first data series.
AttributeDefaultValues
data-efx-data"40,25,15,10" or JSON {"data":[{"label":"A","value":40}]} or {labels, series}. Only the first series is used.
data-efx-labelsTile labels: "Rent|Food|Travel".
data-efx-sourceCSS selector of a Shine table to read.
data-efx-gap2Gap between tiles in px.
data-efx-radius4Tile corner radius.
data-efx-captionstruePrint label and value inside tiles that are big enough.
data-efx-sorttrueLargest tile first (false keeps data order).
data-efx-colorsShine tonesCycled per tile; a single color gives a ramp by rank.
data-efx-height260Chart height in px (0 = element CSS height).
data-efx-prefix / suffixValue formatting, e.g. "$".
data-efx-compact / decimalsfalse / -1Number formatting.
data-efx-tooltip / animatetrueTurn parts off.
data-efx-backgroundfalseDecorative: fills the element behind its content.
data-efx-titleAccessible name.
CSS variableDefaultControls
--efx-chart-1 … 7Shine tonesPalette.
--efx-chart-bg-opacity.35Opacity in background mode.
EventWhen
efx:selectTile clicked / Enter pressed. detail = { index, label, value }.
efx:data (listen)Dispatch with detail { labels, series } to update.

Waterfall chart

chart-waterfall 1.7 KB

Running-total bars: green for increases, red for decreases, primary for totals, joined by connector lines. Tooltip shows the change and the running total.

Profit bridge

Data format
One number per label. Values are deltas (positive = up, negative = down), added to a running total. data-efx-data="100,30,-20,15,-10,0" data-efx-labels="Start|Sales|Refunds|Upsell|Costs|End" data-efx-totals="0|5" data-efx-totals lists the indexes drawn as total bars (from zero; -1 = last). A total bar shows the running total; a non-zero value on it resets the total to that figure. JSON also works: [{"label":"Start","value":100},{"label":"Sales","value":30},{"label":"Refunds","value":-20}] or {"labels":[…],"series":[{"values":[…]}]} (first series only).
ClassWhat it does
efx-chart-waterfallRenders a waterfall from deltas in data-efx-data and total indexes in data-efx-totals.
AttributeDefaultValues
data-efx-dataDeltas: "100,30,-20,15" · JSON [{"label","value"}] · table via data-efx-source.
data-efx-labelsStep names: "Start|Sales|Costs|End".
data-efx-totalsIndexes drawn as total bars, e.g. "0|5" (negative counts from the end).
data-efx-valuestruePrint the value above each bar (+30, −20 …).
data-efx-connectorstrueDashed lines linking one bar to the next.
data-efx-radius3Bar corner radius.
data-efx-colorssuccess / danger / primaryOverride as "total|up|down".
data-efx-prefix / suffixValue formatting, e.g. "$" or "k".
data-efx-compact / decimals / formatNumber formatting (format = registered formatter).
data-efx-height260Chart height in px.
data-efx-tooltip / animate / gridtrueTurn parts off.
data-efx-backgroundfalseDecorative: fills the element behind its content.
data-efx-titleAccessible name.
CSS variableDefaultControls
--sh-success / --sh-danger / --sh-primaryShine tonesUp, down and total colors.
--efx-chart-grid / --efx-chart-textGridlines and axis text.
EventWhen
efx:selectBar clicked / Enter pressed. detail = { index, label, value }.
efx:data (listen)Dispatch with detail { labels, series:[{values}] } to update.

Cycle diagram

diagram-cycle 2.3 KB

Numbered steps on a circle joined by curved, flowing arrows, with an optional centre label. Hover or arrow-key through steps for the description; click a step to fire efx:select. The arrow flow stops for reduced motion.

Product loop

Always iterating

Cycle as a card background.

Data format
Steps are the labels, in order: data-efx-labels="Plan|Build|Measure|Learn" (or JSON [{"label":"Plan","desc":"Pick a bet"}], {"labels":[…]}). Step descriptions show in the tooltip: data-efx-descriptions="Pick a bet|Ship it|…", or a desc field on each JSON item. Arrows run clockwise and the last step loops back to the first. Values are not used; an inline <script type="application/json"> and efx:data ({labels, descriptions} or an items array) also work.
ClassWhat it does
efx-diagram-cycleRenders a loop diagram from data-efx-labels.
AttributeDefaultValues
data-efx-labelsStep names in order: "Plan|Build|Measure|Learn".
data-efx-descriptionsTooltip text per step, "a|b|c".
data-efx-centerLabel in the middle; "|" starts a new line.
data-efx-numberstrueNumber the steps.
data-efx-flowtrueAnimate dashes flowing along the arrows.
data-efx-start0Angle of step 1 in degrees (0 = top, clockwise).
data-efx-height340Chart height in px (0 = element CSS height).
data-efx-colorsShine tonesOne color per step.
data-efx-tooltip / animatetrueTurn parts off.
data-efx-backgroundfalseDecorative: just nodes and arrows, behind the content.
data-efx-titleAccessible name (else aria-label or first heading).
CSS variableDefaultControls
--efx-chart-1 … 7Shine tonesStep colors.
--efx-chart-textmuted textArrows.
--efx-chart-bg-opacity.35Opacity in background mode.
EventWhen
efx:selectStep clicked / Enter pressed. detail = { index, label, value }.
efx:data (listen)Dispatch on the diagram with detail { labels, descriptions } to update it.

Fishbone diagram

diagram-fishbone 2.7 KB

Ishikawa diagram: a spine ending in the problem, angled category bones alternating above and below, and cause labels along each bone. Hover or focus a bone to isolate it. Scales with the container width.

  • People
    • Short staffed
    • Training gaps
    • High turnover
  • Process
    • Manual dispatch
    • No backup route
    • Late cutoffs
  • Vehicles
    • Breakdowns
    • Fuel stops
  • Customers
    • Wrong address
    • Not home
    • Changed slot
  • Weather
    • Snow
    • Floods
  • Systems
    • Stale ETAs
    • Scanner outages
    • Slow routing
Data format
Cause-and-effect (Ishikawa). Either JSON in data-efx-data (or an inline <script type="application/json">): {"problem":"Late deliveries","causes":[{"name":"People","items":["Training","Turnover"]},{"name":"Process","items":["Manual dispatch"]}]} or a nested list inside the element with the problem in data-efx-problem: <ul><li>People<ul><li>Training</li>…</ul></li>…</ul>. Update live with efx:data and the same object.
ClassWhat it does
efx-diagram-fishboneRenders the diagram from JSON or a nested list.
AttributeDefaultValues
data-efx-problemProblem (head of the fish). Overrides the JSON value.
data-efx-dataJSON {problem, causes:[{name, items[]}]}.
data-efx-colorsShine tonesBone colors.
data-efx-titleAccessible name.
CSS variableDefaultControls
--efx-chart-1 … 7Shine tonesBone palette.
EventWhen
efx:selectBone clicked / Enter pressed. detail = { index, label, items, problem }.
efx:data (listen)Dispatch with detail { problem, causes } to update.

Flow diagram

diagram-flow 6.7 KB

One engine for flowcharts, process maps, swimlanes, architecture and data-flow diagrams, state machines and ER/UML cards. Your nodes stay real HTML; orthogonal connectors are drawn behind them and redraw on resize. Hover or focus a node to light up its connections.

Start
Receive order
In stock?
Ship order
Backorder
Done
Browser
CDN
API
Worker
Postgres
Redis
Request
Triage
Refund?
Issue refund
Notified
Idle
Running
Paused
Done
Failed
usersid PKemailname
ordersid PKuser_id FKplaced_at
order_itemsorder_id FKproduct_id FKqty
productsid PKskuprice
Data format
Nodes are ordinary HTML children with an id; connections go in data-efx-edges, separated by |: data-efx-edges="start>check|check>ok:Yes|check>fix:No|fix~>check" Edge styles: a>b solid arrow, a~>b dashed, a=>b thick, a<>b both ways. Text after : is the label. ER cardinality: a label such as 1..n, 1..0n, 01..n (1, n, 0n = zero-or-many, 01 = zero-or-one) draws crow's-foot markers instead of text. Shapes via data-efx-shape: box (default), pill, diamond, circle, db, doc, dot, end, table. Tone via data-efx-tone (primary, accent, success, warning, danger, info, secondary, or 1–7). Placement: data-efx-cell="col,row[,colspan,rowspan]", or data-efx-layout="auto", or swimlanes (data-efx-lanes + data-efx-lane).
ClassWhat it does
efx-diagram-flowThe diagram container. Children with ids are nodes.
data-efx-group="Name"On a wrapper element: labelled dashed boundary around the nodes inside (zones, deployment boxes). Add data-efx-cols to lay it out as a grid.
AttributeDefaultValues
data-efx-edgesConnections: "a>b|b>c:label|c~>a". Operators > ~> => <>.
data-efx-layout"auto" = layered layout (longest-path ranks, barycenter ordering) for the container’s direct children. Empty = place with data-efx-cell or let it flow.
data-efx-directionTBAuto layout direction: TB (top to bottom) or LR.
data-efx-cols0Grid columns when using data-efx-cell (inferred from the cells if 0). Also valid on a group.
data-efx-lanesSwimlane names "Customer|Support|Billing". Nodes pick a lane with data-efx-lane="Support"; column comes from the flow rank or data-efx-cell.
data-efx-routeorth"orth" elbow connectors, "curve" or "straight".
data-efx-flowfalseAnimated dots travelling along each connector (off for reduced motion).
data-efx-colorsShine tonesPalette for numeric tones (data-efx-tone="3").
data-efx-titleAccessible name.
CSS variableDefaultControls
--efx-diagram-gap3rem 3.5remGap between nodes.
--efx-lane-h5.5remMinimum swimlane height.
--efx-edgetext-mutedDefault connector color (a node tone colors its outgoing edges).
--efx-nper toneNode accent color; set it on a node to override.
EventWhen
efx:selectNode clicked / Enter or Space pressed. detail = { id, label, index }.

Pyramid

chart-pyramid 2.1 KB

Layered pyramid (or inverted triangle) with stacked tiers, optional value-sized bands and leader-lined side notes. Tiers stagger in. Click a legend key to hide a tier, click a tier to fire efx:select.

Planning layers

Foundations first

Pyramid as a card background.

Data format
Tiers are the labels, top to bottom: data-efx-labels="Vision|Strategy|Tactics|Tasks". Without values every tier gets the same height. Add values (data-efx-data="1,3,6,12", JSON [{"label":"Vision","value":1}], or a table via data-efx-source) and tier heights follow them (set data-efx-equal to ignore them). Side notes are one per tier, in the same order: data-efx-notes="Why|Where|How|What". Only the first series is used.
ClassWhat it does
efx-chart-pyramidRenders a pyramid from data-efx-labels (and optional values).
AttributeDefaultValues
data-efx-labelsTier names top → bottom: "A|B|C".
data-efx-dataOptional values "1,3,6,12": tier heights follow them.
data-efx-equalfalseEqual tier heights even when values exist.
data-efx-invertedfalsePoint the triangle down (widest tier on top).
data-efx-notesSide annotations, one per tier "Why|Where|How".
data-efx-gap3Gap between tiers in px.
data-efx-height320Chart height in px (0 = element CSS height).
data-efx-colorsShine tonesOne color per tier.
data-efx-legend / tooltip / animatetrueTurn parts off.
data-efx-backgroundfalseDecorative: just the tiers, behind the content.
data-efx-titleAccessible name (else aria-label or first heading).
CSS variableDefaultControls
--efx-chart-1 … 7Shine tonesTier colors.
--efx-chart-textmuted textSide notes.
--efx-chart-bg-opacity.35Opacity in background mode.
EventWhen
efx:selectTier clicked / Enter pressed. detail = { index, label, value }.
efx:data (listen)Dispatch on the chart with detail { labels, series } to update it.

Quadrant matrix

chart-quadrant 2.7 KB

Prioritisation 2×2 with tinted quadrants, axis titles and labelled dots whose labels nudge apart when they would collide. Hover or arrow-key for details, click a dot to fire efx:select.

Roadmap bets

Portfolio health

The matrix sits behind this card as a background.

Data format
A list of items, each with a position: [{"label":"Search","x":20,"y":80},{"label":"Rewrite","x":85,"y":70,"r":8,"group":"Core"}]. x and y run 0–100 unless you set data-efx-x-domain="0,10" / data-efx-y-domain. Optional r sizes the dot (bubble) and group colors it. Quadrants are named top-left | top-right | bottom-left | bottom-right in data-efx-quadrants. Data can sit in data-efx-data, an inline <script type="application/json">, or arrive through efx:data as an array (or {items:[…]}).
ClassWhat it does
efx-chart-quadrantRenders a 2×2 matrix from a list of {label, x, y} items.
AttributeDefaultValues
data-efx-dataJSON items [{"label","x","y","r?","group?"}].
data-efx-quadrantsNames "Quick wins|Big bets|Fill-ins|Money pits" (top-left, top-right, bottom-left, bottom-right).
data-efx-x-label / y-labelAxis titles, e.g. "Effort →".
data-efx-x-domain / y-domain0,100Value range of each axis, e.g. "0,10".
data-efx-height360Chart height in px (0 = element CSS height).
data-efx-colorsShine tonesPalette; groups and quadrant tints use it in order.
data-efx-tooltip / animatetrueTurn parts off.
data-efx-backgroundfalseDecorative: tinted quadrants and dots only, behind the content.
data-efx-titleAccessible name (else aria-label or first heading).
CSS variableDefaultControls
--efx-chart-1 … 7Shine tonesPalette.
--efx-chart-textmuted textAxis titles and quadrant names.
--efx-chart-bg-opacity.35Opacity in background mode.
EventWhen
efx:selectDot clicked / Enter pressed. detail = { index, label, value, series }.
efx:data (listen)Dispatch on the chart with detail = an items array to update it.

Sequence diagram

diagram-sequence 6.6 KB

Draws a UML sequence diagram from a few lines of text: lifelines, sync / return / async arrows, self-messages, notes, loop / alt / opt frames and activation bars. Hover a message to light it and its participants; arrow keys step through messages; data-efx-play draws it in as you scroll. A screen-reader list narrates every step.

Data format
Plain text, one statement per line, inside an inline <script type="text/plain"> (or data-efx-data, or a <pre> that stays readable without JS). Client -> API: GET /me solid sync · API --> Client: 401 dashed return · Client ->> Queue: enqueue async open arrow (->+ / -->- activate / deactivate). note over API: text / note left of A / note right of A / note over A,B · loop alt opt par … else … end frames (nestable) · participant API as "Gateway" · activate X / deactivate X · autonumber · title. Participants appear in order of first mention. JSON works too: {"participants":["A","B"],"messages":[{"from":"A","to":"B","text":"hi","kind":"sync|return|async"},{"note":"x","over":"B"},{"frame":"loop","label":"retry"},{"end":true}]}. Update with efx:data (text or object).
ClassWhat it does
efx-diagram-sequenceContainer; the text lives in an inline script (or data-efx-data).
AttributeDefaultValues
data-efx-dataThe diagram text or JSON (otherwise read from the inline <script type="text/plain"> / <pre>).
data-efx-playfalseDraw messages in one by one when scrolled into view (static for reduced motion).
data-efx-step420Play: ms between messages.
data-efx-activationsfalseAutomatic activation bars: a sync/async message activates its target until it returns.
data-efx-numbersfalseNumber the messages (or write <code>autonumber</code>).
data-efx-bottomfalseRepeat participant boxes at the bottom.
data-efx-gap0Minimum px between lifelines (0 = auto).
data-efx-colorsShine tonesParticipant accent colors.
data-efx-tooltiptrueKeyboard-step tooltip.
data-efx-titleAccessible name.
CSS variableDefaultControls
--efx-seq-linemuted textArrow color.
--efx-seq-notetinted warningNote fill.
EventWhen
efx:selectMessage clicked. detail = { index, label, from, to }.
efx:data (listen)Dispatch with detail = new text or JSON to redraw.

Tree diagram

diagram-tree 4.9 KB

Turns a nested list into an org chart, tree or mind map. JS lays the nodes out and draws curved or elbow connectors; the list stays real, accessible HTML (role=tree). Click, Enter or Space folds a branch (animated); arrow keys move between nodes.

  • CEO
    • CTO
      • Platform
      • Mobile
      • Data
    • CFO
      • Finance
      • Legal
    • COO
      • Support
      • Ops
  • Launch
    • Marketing
      • Blog
      • Social
    • Product
      • Beta
      • Docs
    • Sales
      • Pricing
      • Demos
    • Risks
      • Load
      • Legal
  • src
    • charts
      • _lib.js
      • chart-bar.js
    • features
      • reveal.js
      • tilt.js
    • core.js
Data format
A plain nested list. The node is the first element (or text) of each <li>; a nested <ul> holds its children. <ul class="efx-diagram-tree"><li data-efx-tone="primary"><span>CEO</span><ul><li>CTO</li><li>CFO</li></ul></li></ul> Per-node: data-efx-tone="success" (any Shine tone or CSS colour), data-efx-collapsed to start folded. Links, headings and other markup inside a node are kept. Without JS it stays a readable nested list.
ClassWhat it does
efx-diagram-treeOn a <ul>: lay the list out as a diagram.
AttributeDefaultValues
data-efx-directiondown"down" (org chart) or "right" (horizontal tree).
data-efx-layouttree"mindmap" centres the root and splits its children left/right.
data-efx-linkselbow"elbow", "curve" or "straight" connectors.
data-efx-collapsibletrueBranches fold on click / Enter / Space.
data-efx-collapse0Start folded from this depth (1 = fold every branch below the root's children). 0 = all open.
data-efx-gap16Gap between siblings in px.
data-efx-level-gap44Gap between levels in px.
data-efx-toneDefault tone for every node (a Shine tone name).
data-efx-animatetrueEntrance + fold animation (off for reduced motion).
data-efx-titleAccessible name (or aria-label on the list).
CSS variableDefaultControls
--efx-tree-linemutedConnector colour.
--efx-toneper nodeNode accent + connector colour; set by data-efx-tone.
EventWhen
efx:selectNode clicked / Enter. detail = { label, depth }.
efx:toggleBranch folded or unfolded. detail = { label, expanded }.

Venn diagram

chart-venn 2.9 KB

Area-proportional two- or three-set Venn with translucent blended circles, set names, totals and overlap counts. Hover a region (or arrow through them) for a tooltip; click fires efx:select.

Who uses what

Overlap

Venn as a card background.

Data format
A list of regions: [{"sets":["Design"],"size":12},{"sets":["Dev"],"size":10},{"sets":["Design","Dev"],"size":4}]. A one-set entry is that set's total size (circle area ∝ size); a two- or three-set entry is the size of that overlap. Two-set overlaps are exact; with three sets each pair overlap is exact and the centre region is approximate. sets may also be written "Design&Dev". Up to three sets. Data can sit in data-efx-data, an inline <script type="application/json">, or arrive through efx:data as an array.
ClassWhat it does
efx-chart-vennRenders a 2- or 3-set Venn from region sizes.
AttributeDefaultValues
data-efx-dataJSON regions [{"sets":["A"],"size":12},{"sets":["A","B"],"size":4}].
data-efx-opacity0.4Circle fill opacity.
data-efx-height300Chart height in px (0 = element CSS height).
data-efx-colorsShine tonesOne color per set "#f43f5e|#8b5cf6|#10b981".
data-efx-prefix / suffix / compact / decimalsNumber formatting of the counts.
data-efx-tooltip / animatetrueTurn parts off.
data-efx-backgroundfalseDecorative: just the circles, behind the content.
data-efx-titleAccessible name (else aria-label or first heading).
CSS variableDefaultControls
--efx-chart-1 … 3Shine tonesSet colors.
--efx-chart-bg-opacity.35Opacity in background mode.
EventWhen
efx:selectRegion clicked / Enter pressed. detail = { index, label, value }.
efx:data (listen)Dispatch on the chart with detail = a regions array to update it.

Arc diagram

viz-arc 2.2 KB

Nodes on a line, links drawn as arcs above it. Hover a node to highlight its arcs, hover an arc for its endpoints and value.

Character co-appearances

6 nodes
Data format
Same graph JSON as the network graph: {"nodes":[{"id","group?","label?"}],"links":[{"source","target","value?"}]}. Nodes sit on a line in the given order (or data-efx-sort="group|degree"); link width = value. Example: {"nodes":[{"id":"a"},{"id":"b"},{"id":"c"}],"links":[{"source":"a","target":"c","value":3}]}
ClassWhat it does
efx-viz-arcRenders an arc diagram from graph JSON.
AttributeDefaultValues
data-efx-dataGraph JSON (see data format).
data-efx-sortOrder nodes by "group" or "degree" (default: input order).
data-efx-radius5Base node radius.
data-efx-height280Chart height in px.
data-efx-colorsShine tonesGroup colors.
data-efx-tooltip / animatetrueTurn parts off.
data-efx-backgroundfalseDecorative: fills the element behind its content.
data-efx-titleAccessible name.
CSS variableDefaultControls
--efx-chart-1 … 7Shine tonesGroup palette.
EventWhen
efx:selectNode or arc clicked / Enter. detail = { index, label, value, series }.
efx:data (listen)Dispatch with a new graph { nodes, links } as detail.

Bump and slope

viz-rank 2.3 KB

Bump chart: smooth rank lines with dots and end labels. Slope chart: two periods side by side. Hover or arrow through items to highlight one and read its path in the tooltip.

Language popularity

Revenue by team

Data format
Periods = data-efx-labels, one series per item with one value per period; ranks are computed per period (highest value = #1). {"labels":["2023","2024","2025"],"series":[{"name":"Rust","data":[5,8,9]},{"name":"Go","data":[7,7,6]}]} Already have ranks? Add data-efx-ranks and give ranks (1 = best) as the values. Slope mode uses the first and last period and plots the values themselves. Also [{"name","data"}], an inline JSON script, a table via data-efx-source or an efx:data event.
ClassWhat it does
efx-viz-rankRenders a bump or slope chart.
AttributeDefaultValues
data-efx-modebump<code>bump</code> (ranks over periods) or <code>slope</code> (first vs last period).
data-efx-dataItems and values (see data format).
data-efx-labelsPeriod names: "2023|2024|2025".
data-efx-ranksfalseValues are already ranks (1 = best).
data-efx-smoothtrueCurved connectors (false = straight).
data-efx-heightChart height in px.
data-efx-colorsShine tonesColors "#f43f5e|#8b5cf6".
data-efx-prefix / suffixValue formatting, e.g. "$" or "%".
data-efx-compact / decimals / format12.3k style, fixed decimals, or a registered formatter name.
data-efx-legend / tooltip / animatetrueTurn parts off.
data-efx-backgroundfalseDecorative: fills the element behind its content (no axes/tooltip).
data-efx-titleAccessible name (else aria-label or first heading).
CSS variableDefaultControls
--efx-chart-1 … 7Shine tonesPalette.
--efx-chart-grid / --efx-chart-textmutedGridlines and axis labels.
--efx-chart-bg-opacity.35Opacity in background mode.
EventWhen
efx:selectItem clicked / Enter pressed. detail = { index, label, value, series }.
efx:data (listen)Dispatch with detail { labels, series } to update.

Chord diagram

viz-chord 2.2 KB

Chord diagram: outer arcs per group, ribbons sized by flow between groups. Hover a group to highlight its ribbons, hover a ribbon for both directions.

Migration between regions

Data format
Square flow matrix: row = source, column = target; labels name the groups. {"labels":["A","B","C"],"matrix":[[0,5,2],[3,0,4],[1,2,0]]} or data-efx-data="[[0,5,2],[3,0,4],[1,2,0]]" with data-efx-labels="A|B|C". Hover a ribbon for "A → B: x, B → A: y"; hover an outer arc to isolate its flows.
ClassWhat it does
efx-viz-chordRenders a chord diagram from a square matrix.
AttributeDefaultValues
data-efx-dataMatrix JSON (see data format).
data-efx-labelsGroup labels "A|B|C".
data-efx-gap0.04Gap between groups in radians.
data-efx-height380Chart height in px.
data-efx-colorsShine tonesGroup colors.
data-efx-prefix / suffix / compactValue formatting.
data-efx-tooltip / animatetrueTurn parts off.
data-efx-backgroundfalseDecorative: fills the element behind its content.
data-efx-titleAccessible name.
CSS variableDefaultControls
--efx-chart-1 … 7Shine tonesGroup palette.
EventWhen
efx:selectArc or ribbon clicked / Enter. detail = { index, label, value }.
efx:data (listen)Dispatch with { labels, matrix } as detail.

Circle packing

viz-pack 3.4 KB

Nested circles packed by value. Click a circle to zoom into it (animated), click the background or the focused circle to zoom back out. Leaf labels appear when they fit.

Bundle size by package

Portfolio
Data format
Hierarchy JSON: {"name","value?","children":[…]}. Leaves carry value (default 1), parents sum their children. Example: {"name":"root","children":[{"name":"a","value":3},{"name":"b","children":[{"name":"c","value":2},{"name":"d","value":1}]}]}
ClassWhat it does
efx-viz-packRenders circle packing from hierarchy JSON.
AttributeDefaultValues
data-efx-dataHierarchy JSON (see data format).
data-efx-padding0.15Gap between circles, as a fraction of the average leaf radius.
data-efx-height420Chart height in px.
data-efx-colorsShine tonesColors for top-level branches.
data-efx-prefix / suffix / compactValue formatting.
data-efx-tooltip / animatetrueTurn parts off (animate off = instant zoom).
data-efx-backgroundfalseDecorative: fills the element behind its content.
data-efx-titleAccessible name.
CSS variableDefaultControls
--efx-chart-1 … 7Shine tonesBranch palette.
EventWhen
efx:selectCircle clicked / Enter (also zooms). detail = { index, label, value, series }.
efx:data (listen)Dispatch with a new hierarchy as detail.

Distribution

viz-distribution 3.2 KB

Gaussian-KDE density curves, violins, ridgelines or beeswarms from raw samples. Silverman bandwidth by default. Hover for count, median and quartiles; click a legend key to hide a group.

Response time by region (ms)

412 ms

median latency

Data format
Raw samples, not summaries. Groups = data-efx-labels (or "labels"), one array of numbers per group per series. {"labels":["Fri","Sat"],"series":[{"name":"Tips","data":[[2,3,3,5,8],[4,6,6,9,15]]}]} Several series → "series":[{"name":"2025","data":[[…],[…]]},{"name":"2026","data":[[…],[…]]}] (one color per series). Shorthands: [1,2,2,3] (one group) · [[…],[…]] (one group per array). Also an inline <script type="application/json"> or an efx:data event.
ClassWhat it does
efx-viz-distributionRenders a distribution plot; pick the shape with data-efx-mode.
AttributeDefaultValues
data-efx-modedensity<code>density</code> (overlaid curves) · <code>violin</code> · <code>ridgeline</code> · <code>beeswarm</code>.
data-efx-dataSamples as JSON (see data format).
data-efx-labelsGroup names: "Fri|Sat|Sun".
data-efx-namesSeries names.
data-efx-bandwidthautoKDE bandwidth in value units (default: Silverman rule of thumb).
data-efx-overlap0.8Ridgeline: how far peaks rise into the row above (0 = none).
data-efx-gridtrueGridlines.
data-efx-heightChart height in px.
data-efx-colorsShine tonesColors "#f43f5e|#8b5cf6".
data-efx-prefix / suffixValue formatting, e.g. "$" or "%".
data-efx-compact / decimals / format12.3k style, fixed decimals, or a registered formatter name.
data-efx-legend / tooltip / animatetrueTurn parts off.
data-efx-backgroundfalseDecorative: fills the element behind its content (no axes/tooltip).
data-efx-titleAccessible name (else aria-label or first heading).
CSS variableDefaultControls
--efx-chart-1 … 7Shine tonesPalette.
--efx-chart-grid / --efx-chart-textmutedGridlines and axis labels.
--efx-chart-bg-opacity.35Opacity in background mode.
EventWhen
efx:selectCurve, violin or dot clicked / Enter pressed. detail = { index, label, value, series }.
efx:data (listen)Dispatch on the element with detail { labels, series:[{name, data:[[…]]}] } to update it.

Map

viz-map 4.0 KB

A dependency-free map for your own GeoJSON: choropleth regions with a one-colour ramp and legend, sized bubbles, animated route arcs, hover tooltips and optional wheel/drag zoom. Mercator, equirectangular or natural-earth projection, fitted to the bounds. The example uses a made-up map, so it works offline.

Sales by region

Coverage

Map as a card background

Data format
No map data is bundled. Supply a GeoJSON FeatureCollection of Polygon / MultiPolygon features (e.g. from Natural Earth, simplified) as an inline <script type="application/json">, data-efx-geo='{…}' or data-efx-geo-url="/world.geojson" (same origin or CORS). TopoJSON is not read. Choropleth data-efx-data='[{"id":"FR","value":12},{"name":"Spain","value":7}]' matches feature.id or properties.name (case-insensitive); also {"FR":12}. Bubbles data-efx-points='[{"lat":48.8,"lon":2.3,"value":9,"label":"Paris"}]' · routes data-efx-routes='[{"from":[lat,lon],"to":[lat,lon]}]' (arrays are [lat, lon]). Live update: efx:data with detail {geo, data, points, routes} (any subset).
ClassWhat it does
efx-viz-mapRenders a GeoJSON map with optional choropleth, bubbles and routes.
AttributeDefaultValues
data-efx-geo / data-efx-geo-urlGeoJSON inline, or a URL to fetch (also inline script JSON).
data-efx-projectionmercator<code>mercator</code>, <code>equirectangular</code> or <code>natural</code> (natural earth).
data-efx-dataChoropleth values [{id|name, value}] matched to feature.id / properties.name.
data-efx-pointsBubbles [{lat, lon, value, label}], radius by sqrt(value).
data-efx-routesCurved animated arcs [{from:[lat,lon], to:[lat,lon]}].
data-efx-steps6Colour steps in the ramp.
data-efx-zoomfalseWheel to zoom, drag to pan, double-click to reset.
data-efx-colorsShine tonesFirst colour = choropleth ramp, second = bubbles and routes.
data-efx-prefix / suffix / compact / decimals / formatValue formatting.
data-efx-heightautopx; default follows the map aspect ratio.
data-efx-legend / tooltip / animatetrueTurn parts off.
data-efx-backgroundfalseDecorative: fills the element behind its content.
data-efx-titleAccessible name.
CSS variableDefaultControls
--efx-chart-1 … 7Shine tonesPalette; ramps mix colour 1 with --sh-surface.
EventWhen
efx:selectRegion or bubble clicked / Enter pressed. detail = { index, label, value }.
efx:data (listen)detail { geo, data, points, routes } replaces any of them.

Marimekko

viz-marimekko 1.7 KB

Mosaic chart: column widths show each category's size, stacked segments show its composition. Hover for the value, share of the column and share of the total; legend keys hide segments.

Sales by region and channel

Data format
Columns = data-efx-labels (width ∝ column total); series = segments stacked inside each column (height ∝ share). {"labels":["Asia","Europe","US"],"series":[{"name":"Mobile","data":[40,20,30]},{"name":"Desktop","data":[10,25,25]}]} Same inputs as every Effix chart: data-efx-data, inline JSON script, data-efx-source table (first column = columns) or an efx:data event.
ClassWhat it does
efx-viz-marimekkoRenders a Marimekko / mosaic chart.
AttributeDefaultValues
data-efx-dataSegments per column (see data format).
data-efx-labelsColumn names: "Asia|Europe|US".
data-efx-namesSegment names.
data-efx-insidepercentCell labels: <code>percent</code>, <code>value</code> or <code>none</code> (shown only where they fit).
data-efx-gap2Pixels between columns.
data-efx-heightChart height in px.
data-efx-colorsShine tonesColors "#f43f5e|#8b5cf6".
data-efx-prefix / suffixValue formatting, e.g. "$" or "%".
data-efx-compact / decimals / format12.3k style, fixed decimals, or a registered formatter name.
data-efx-legend / tooltip / animatetrueTurn parts off.
data-efx-backgroundfalseDecorative: fills the element behind its content (no axes/tooltip).
data-efx-titleAccessible name (else aria-label or first heading).
CSS variableDefaultControls
--efx-chart-1 … 7Shine tonesPalette.
--efx-chart-grid / --efx-chart-textmutedGridlines and axis labels.
--efx-chart-bg-opacity.35Opacity in background mode.
EventWhen
efx:selectCell clicked / Enter pressed. detail = { index, label, value, series }.
efx:data (listen)Dispatch with detail { labels, series } to update.

Network graph

viz-network 3.2 KB

Force-directed graph with its own tiny physics (springs, repulsion, collisions) that cools and stops. Drag nodes, zoom with the wheel, hover to highlight neighbours, arrow-key between nodes. Reduced motion renders the settled layout statically.

Team collaboration

Everything is connected

A live graph drifting behind this card.

Data format
Graph JSON: {"nodes":[{"id","group?","size?","label?"}],"links":[{"source","target","value?"}]}. source/target are node ids. Colour = group, radius = size, link width = value. Pass it via data-efx-data or an inline <script type="application/json">. Example: {"nodes":[{"id":"a","group":"x"},{"id":"b","group":"y"}],"links":[{"source":"a","target":"b"}]}
ClassWhat it does
efx-viz-networkRenders a force-directed graph from graph JSON.
AttributeDefaultValues
data-efx-dataGraph JSON (see data format).
data-efx-labelfalsePrint node labels (label or id).
data-efx-zoomtrueWheel zoom and background pan.
data-efx-link-distance70Preferred link length in px.
data-efx-charge60Repulsion strength between nodes.
data-efx-radius5Average node radius.
data-efx-height420Chart height in px.
data-efx-colorsShine tonesGroup colors "#f43f5e|#8b5cf6".
data-efx-tooltip / animatetrueTurn parts off (animate off = static layout).
data-efx-backgroundfalseDecorative: fills the element behind its content.
data-efx-titleAccessible name.
CSS variableDefaultControls
--efx-chart-1 … 7Shine tonesGroup palette.
--efx-chart-textmuted textLink color.
EventWhen
efx:selectNode clicked / Enter pressed. detail = { index, label, value, series }.
efx:data (listen)Dispatch with a new graph { nodes, links } as detail.

Parallel coordinates

viz-parallel 2.7 KB

One vertical axis per dimension with a polyline per row. Hover a line to highlight it, drag on an axis to brush a range (other lines fade), double-click an axis to clear its brush.

Cars compared

Compare options

Every line is a candidate.

Data format
Rows of objects: one numeric field per axis, optional name and group (line color). [{"name":"Golf","group":"Hatch","mpg":34,"hp":105,"weight":1.2},{"name":"Civic","group":"Sedan","mpg":38,"hp":130,"weight":1.3}] Choose/order axes with data-efx-dims="mpg|hp"; the group field is data-efx-group (default "group"). Or tabular: data-efx-labels = axes, series = rows: [{"name":"Golf","data":[34,105,1.2]}]. Update with an efx:data event (rows array, or { labels, series }).
ClassWhat it does
efx-viz-parallelRenders parallel coordinates from rows of numeric fields.
AttributeDefaultValues
data-efx-dataRows (see data format).
data-efx-dimsall numeric keysAxes to show, in order: "mpg|hp|weight".
data-efx-groupgroupRow field used for line color and legend.
data-efx-opacity0.65Line opacity.
data-efx-heightChart height in px.
data-efx-colorsShine tonesColors "#f43f5e|#8b5cf6".
data-efx-prefix / suffixValue formatting, e.g. "$" or "%".
data-efx-compact / decimals / format12.3k style, fixed decimals, or a registered formatter name.
data-efx-legend / tooltip / animatetrueTurn parts off.
data-efx-backgroundfalseDecorative: fills the element behind its content (no axes/tooltip).
data-efx-titleAccessible name (else aria-label or first heading).
CSS variableDefaultControls
--efx-chart-1 … 7Shine tonesPalette.
--efx-chart-grid / --efx-chart-textmutedGridlines and axis labels.
--efx-chart-bg-opacity.35Opacity in background mode.
EventWhen
efx:selectLine clicked / Enter pressed. detail = { index, label, value, series }.
efx:data (listen)Dispatch with detail = rows array or { labels, series } to update.

Word cloud

viz-wordcloud 2.3 KB

Words sized by weight (square-root scale) and packed along an Archimedean spiral without overlap. Optional 90° or custom rotation, hover for the count, click fires efx:select. Text is inserted as text, never HTML.

What people talk about

Release notes
Data format
Weighted words, or raw text to count. data-efx-data="design:40|code:28|motion:19" ("word:weight" split by |) JSON: [{"text":"design","value":40},{"text":"code","value":28}] (also word/weight/count) Raw text: data-efx-text="long text…" counts words (lower-cased, ~60 English stop words and 1-letter words dropped). Also an inline <script type="application/json">, or live: efx:data with detail {words:[…]} or {text:"…"}.
ClassWhat it does
efx-viz-wordcloudRenders a word cloud from weighted words or raw text.
AttributeDefaultValues
data-efx-data"word:weight|word:weight" or JSON [{text,value}].
data-efx-textRaw text; words are counted, stop words removed.
data-efx-min-size / max-size12 / 56Font size range in px.
data-efx-rotate0Angles to pick from, e.g. "0|90" or "0|-30|30". The biggest word stays at the first angle.
data-efx-max80Maximum words shown.
data-efx-padding2Gap between words in px.
data-efx-heightautoChart height in px (default half the width, min 200).
data-efx-colorsShine tonesPalette "#f43f5e|#8b5cf6", cycled by rank.
data-efx-tooltip / animatetrueTurn parts off.
data-efx-backgroundfalseDecorative: fills the element behind its content.
data-efx-titleAccessible name.
CSS variableDefaultControls
--efx-chart-1 … 7Shine tonesPalette.
EventWhen
efx:selectWord clicked / Enter pressed. detail = { index, label, value }.
efx:data (listen)Dispatch with detail { words:[{text,value}] } or { text } to update.