This bar tracks how far you have scrolled through this article.
Keep scrolling the page.
effects 65.8 KB gzip charts add-on 34.2 KB core 2.6 KB MIT · 0 dependencies
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
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>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">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>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
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>efx-* class — picks the feature. Combine as many as you like on one element.data-efx-* attributes — behaviour options (counts, speeds, triggers). Each feature lists its options below.--efx-* CSS variables — visual knobs. Colors fall back to Shine: --efx-color → --sh-tone → --sh-primary.querySelectorAll); missing features cost nothing. Canvas features are lazy and every loop pauses off-screen and in hidden tabs.| Switch | Effect |
|---|---|
<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-skip | On 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
The full build is already small, but you can cut it further. Tick features to see the size and the command.
Estimated: 100.0 KB gzip
node build.jsimport { define, init } from 'effix/core';Visual editors & SPAs
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);| Method | What 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.charts | The chart toolkit (chart, COMMON, scales, nice, linePath, arcPath, s, axes…) for building your own chart types. |
Data input
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.
{
"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.
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>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>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>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>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));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
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:
data-efx-shape="heart"| Kind | Used by | Signature |
|---|---|---|
CSS | Animations, Reveal on scroll | --efx-anim |
Events | Scene reel | efx:scene |
easing | Counter, Scroll scrub | (t: 0..1) => number |
sparkle-shape | Sparkles | fn(size) -> svg markup string or Node |
confetti-shape | Confetti | (ctx, size, piece) => void |
ambient-mode | Ambient backgrounds | { count(area)->n, spawn(p,S,first), step(p,S)->alive, draw(ctx,p,S), blend?, ptr? } |
particle-shape | Particles | (ctx2d, size, particle) => void |
trail-shape | Cursor trail | (size, arg) => Node |
divider-shape | Shape dividers | { periodic: 0|1, layers: [[y0, side, tile(ox) -> "L x,y…"]], ops?: [opacity…] } |
Effix.add | Shape morph | 'shape', name, d |
audio-viz | Audio visualizer | (ctx2d, { freq, time, level, count }, w, h, colors) => void |
Attributes | Pricing toggle | [data-efx-period] |
Event | Pricing toggle, Toast | efx:period |
Trigger | Toast | [data-efx-toast="#id"] |
format | All charts (data-efx-format) | (value, options) => string |
Effix.define | Your 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
Every demo is live: edit the HTML under it and the demo restarts with your options.
animate
3.0 KBReady-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.
| Class | What it does |
|---|---|
efx-fade-in · efx-fade-out · efx-fade-in-up · efx-fade-in-down | Fades. Entrance anims start hidden. |
efx-bounce · efx-bounce-in · efx-bounce-out · efx-bounce-up · efx-bounce-down | Bounces (entrance, exit, directional). |
efx-slide-up · efx-slide-down · efx-slide-left · efx-slide-right | Slides from the element's own size. |
efx-pop · efx-pop-in · efx-pop-elastic · efx-rotate · efx-rotate-in · efx-spin · efx-spin-reverse | Pop, 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-shake | Scale, zoom and 3D flips. |
efx-wobble · efx-pulse · efx-heartbeat · efx-jello · efx-tada · efx-swing · efx-rubber | Attention seekers. |
efx-anim | Generic: plays whatever --efx-anim names (use with your own keyframes). |
efx-hover · efx-focus · efx-active | Trigger (pure CSS): play on hover, focus-visible/focus-within, or while pressed. |
efx-load | Trigger: plays once on load (the default with no trigger class; supports .efx-stagger). |
efx-click | Trigger: replays on every click. |
efx-scroll | Trigger: plays when scrolled into view (entrance anims stay hidden until then, only once JS runs). |
efx-loop | Repeat forever (or data-efx-repeat="3"). |
efx-underline-grow | Underline that grows in on hover/focus and leaves out the other side. |
efx-underline-left · efx-underline-right · efx-underline-center | Underline wipes in from that origin on hover/focus-visible. |
efx-stagger | Container: cascades delays of .efx-load / .efx-scroll children (data-efx-stagger="80"). |
| Attribute | Default | Values |
|---|---|---|
data-efx-delay | 0 | Extra delay in ms (click/load/scroll triggers). |
data-efx-once | true | efx-scroll: false = replay each time it re-enters. |
data-efx-threshold | 0.15 | efx-scroll: how far into the viewport (0-1) before it plays. |
data-efx-repeat | Iteration count (number or "infinite"); CSS handles 2-5 and infinite without JS. | |
data-efx-stagger | 80 | On .efx-stagger: ms between children. |
data-efx-from | first | On .efx-stagger: where the cascade starts: first · last · center · edges · random · or an item index (0-based). |
data-efx-grid | On .efx-stagger: "cols,rows" (e.g. "4,3") or "auto" (measures item positions) to delay by 2D distance from the origin. | |
data-efx-axis | On .efx-stagger with a grid: x or y to measure distance on one axis only. | |
data-efx-ease | linear | On .efx-stagger: easing name (see Effix.add("easing")) distributing the delays along a curve. |
data-efx-total | On .efx-stagger: spread the cascade across this many ms in total instead of ms per step. |
| CSS variable | Default | Controls |
|---|---|---|
--efx-duration | 700ms | Animation length. |
--efx-ease | cubic-bezier(.22,1,.36,1) | Easing. |
--efx-delay | 0s | Start delay. |
--efx-iter | 1 | Iteration count. |
--efx-distance | 24px | Travel for fade-in-up/down. |
--efx-color | Shine tone/primary | Underline color. |
--efx-thickness | 2px | Underline thickness. |
| Kind | Signature | What it is |
|---|---|---|
CSS | --efx-anim | Custom 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
1.1 KBRepeats 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.
| Class | What it does |
|---|---|
efx-nudge | Element to nudge (button, bell icon, CTA). |
| Attribute | Default | Values |
|---|---|---|
data-efx-every | 6000 | Ms between nudges. |
data-efx-anim | shake | shake · wobble · ring, or any animate.css name (pulse, tada, heartbeat, jello...). |
data-efx-times | 0 | Max repeats (0 = until interaction). |
data-efx-delay | 3000 | Ms before the first nudge. |
data-efx-stop | click | click · hover · never. |
data-efx-dot | false | Add a pulsing notification dot top-right (hides on interaction). |
| CSS variable | Default | Controls |
|---|---|---|
--efx-nudge-dot | var(--sh-danger) | Dot color. |
reel
2.6 KBA 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.
Motion for Shine, in one script.
Each scene replays its own effects.
Clip-path reveal.
Loop, pause, or jump with the bar.
| Class | What it does |
|---|---|
efx-reel | The container. Its scene children play in order. |
efx-reel__scene | A scene (or use [data-efx-scene]). Only the current one is visible; the rest are hidden and inert. |
| Attribute | Default | Values |
|---|---|---|
data-efx-autoplay | true | Start playing when visible (never with reduced motion). |
data-efx-loop | false | Restart after the last scene. |
data-efx-controls | true | Inject play/pause button and progress segments. |
data-efx-duration | 3000 | Default scene length in ms (override per scene). |
data-efx-transition | fade | Default transition: fade · slide · wipe · zoom · cut (override per scene). |
| CSS variable | Default | Controls |
|---|---|---|
--efx-reel-t | 600ms | Transition length. |
--efx-color | Shine tone | Progress fill color. |
| Kind | Signature | What it is |
|---|---|---|
Events | efx:scene | Fires on the container with detail.index whenever a scene is entered. Keys: ← → switch scenes, Space plays/pauses. |
ascii
2.4 KBTurns 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.
| Class | What it does |
|---|---|
efx-ascii | On an <img>, <video>, <canvas>, or a block element with data-efx-text. |
efx-ascii__out | Injected <pre> (or <canvas>) holding the art. |
efx-ascii__src | Added to the original image/video/canvas while it is replaced. |
| Attribute | Default | Values |
|---|---|---|
data-efx-cols | 80 | Characters per row (rows follow the aspect ratio). |
data-efx-chars | .:-=+*#%@ | Characters from dark to bright. |
data-efx-invert | false | Flip the brightness mapping (use on light backgrounds). |
data-efx-color | mono | mono (inherits text color, or --efx-ascii-color) · source (per-character color from the image). |
data-efx-text | Render this text large and convert it (use " " for line breaks). Falls back to the element's own text. | |
data-efx-output | pre | pre · canvas. |
data-efx-reveal | true | Scramble-then-settle animation when first visible. |
data-efx-duration | 1200 | Reveal length in ms. |
data-efx-fps | 24 | Frame cap for the reveal and live video. |
data-efx-live | false | On a <canvas> source: re-sample every frame. Videos are always live while playing. |
| CSS variable | Default | Controls |
|---|---|---|
--efx-ascii-color | inherit | Text color of the art. |
distort
0.8 KBLiquid 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.
hover
always
Text warps too.
| Class | What it does |
|---|---|
efx-distort | Image or element to warp. One hidden <svg><filter> per instance, removed on cleanup. |
| Attribute | Default | Values |
|---|---|---|
data-efx-scale | 30 | Maximum displacement in px. |
data-efx-frequency | 0.02 | Noise base frequency (lower = broader waves). |
data-efx-speed | 1 | Animation speed multiplier. |
data-efx-trigger | hover | hover · always (while on screen) · view (one pulse when scrolled in). |
flip
0.9 KBA 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.
Any content, any height.
Press again to flip back.
| Class | What it does |
|---|---|
efx-flip | The card wrapper. |
efx-flip__front | Front face (child of .efx-flip). |
efx-flip__back | Back face (child of .efx-flip). Hidden from assistive tech until shown. |
| Attribute | Default | Values |
|---|---|---|
data-efx-trigger | hover | hover · click. Click mode makes the card a button with aria-pressed. Touch devices always use click. |
data-efx-axis | y | y (horizontal flip) · x (vertical flip). |
data-efx-duration | 600 | Flip time in ms. |
| CSS variable | Default | Controls |
|---|---|---|
--efx-ease | cubic-bezier(.22,1,.36,1) | Easing. |
kenburns
1.0 KBSlow 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.
single image
slideshow
| Class | What it does |
|---|---|
efx-kenburns | An <img> (gets wrapped in a clipping frame) or a wrapper holding one or more <img>. |
| Attribute | Default | Values |
|---|---|---|
data-efx-duration | 12000 | Pan/zoom length in ms; also the slideshow interval. |
data-efx-zoom | 1.15 | End zoom factor. |
| CSS variable | Default | Controls |
|---|---|---|
--efx-kb-x0 … --efx-kb-y1 | random | Per-image start/end translation, set by JS. |
pixelate
1.0 KBMosaic 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.
trigger: view
trigger: hover
| Class | What it does |
|---|---|
efx-pixelate | The <img>, or a wrapper that contains one. |
| Attribute | Default | Values |
|---|---|---|
data-efx-from | 32 | Largest block size in px. |
data-efx-duration | 900 | Transition time in ms. |
data-efx-trigger | view | view (sharpen on scroll-in) · hover (pixelate on hover, sharpen on leave). |
popout
1.0 KBA 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.
| Class | What it does |
|---|---|
efx-popout | The card (give it a size and a radius). |
efx-popout__bg | Background layer, clipped to the card. A div with background-image, or an img. |
efx-popout__fg | Foreground cut-out (transparent PNG/SVG img) that overflows the top and sides. |
| Attribute | Default | Values |
|---|---|---|
data-efx-depth | 20 | Layer travel in px (foreground moves most, background least). |
data-efx-tilt | 8 | Maximum 3D tilt in degrees (pointer). |
data-efx-mode | both | pointer · scroll · both (pointer needs a fine pointer; scroll works on touch). |
mask
1.0 KBA 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.
| Class | What it does |
|---|---|
efx-mask | Wrapper containing the base <img>. |
efx-mask__reveal | Optional second <img> shown inside the spotlight. Without it a colour copy of the base is used. |
| Attribute | Default | Values |
|---|---|---|
data-efx-radius | 120 | Spotlight radius in px (grows in on enter). |
data-efx-soft | 0.4 | Edge softness 0–1. |
data-efx-gray | true | false = leave the base image in colour (use with a different reveal image). |
| CSS variable | Default | Controls |
|---|---|---|
--efx-x / --efx-y / --efx-r | set by JS | Spotlight position and radius, readable for custom styling. |
totop
0.6 KBA button that fades in after scrolling and returns to the top (smooth when motion is allowed).
| Class | What it does |
|---|---|
efx-totop | The button. Fixed bottom-right by default; gets is-shown after scrolling. |
| Attribute | Default | Values |
|---|---|---|
data-efx-show | 400 | Scroll distance in px before it appears. |
data-efx-fixed | true | false = no fixed positioning, place it yourself. |
chapter
1.5 KBA 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.
| Class | What it does |
|---|---|
efx-chapter | The chip (usually position:fixed or sticky). Gets is-empty while no section is in view. |
| Attribute | Default | Values |
|---|---|---|
data-efx-sections | section[data-efx-title] | CSS selector of the sections. Title comes from data-efx-title or the first heading. |
data-efx-ring | true | Show the section progress ring. |
| CSS variable | Default | Controls |
|---|---|---|
--efx-chapter-bg | surface 85% | Chip background. |
--efx-color | Shine tone/primary | Ring color. |
counter
0.8 KBCounts up to the number written in the element when it scrolls into view. Without JS (or with reduced motion) the final value shows.
| Class | What it does |
|---|---|
efx-counter | Element whose text is the final number. |
| Attribute | Default | Values |
|---|---|---|
data-efx-from | 0 | Start value. |
data-efx-to | from text | End value (defaults to the number in the text). |
data-efx-duration | 1600 | Duration in ms. |
data-efx-ease | ease-out-cubic | linear · ease-in · ease-out · ease-in-out · ease-out-cubic · back-out · elastic-out, or any registered easing. |
data-efx-decimals | -1 | Decimal 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-once | true | false = replay every time it re-enters the viewport. |
| Kind | Signature | What it is |
|---|---|---|
easing | (t: 0..1) => number | Shared 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>hscroll
1.0 KBPins a section while vertical scrolling slides a row of panels sideways. On small screens or with reduced motion it becomes a native swipeable row.
Keep scrolling down.
The page moves sideways.
Then continues down.
| Class | What it does |
|---|---|
efx-hscroll | The section. Its height is computed from the track width. |
efx-hscroll__track | Optional child holding the panels. Added automatically if missing. |
| Attribute | Default | Values |
|---|---|---|
data-efx-offset | 0 | Pin this many px below the top (for a sticky header). |
data-efx-snap | false | Settle on the nearest panel when scrolling stops. |
marquee
0.9 KBInfinite scrolling ticker. Content is cloned (aria-hidden) to fill the width; pauses on hover/focus and when off-screen; wraps statically with reduced motion.
| Class | What it does |
|---|---|
efx-marquee | Container whose children scroll endlessly. |
| Attribute | Default | Values |
|---|---|---|
data-efx-speed | 60 | Pixels per second. |
data-efx-direction | left | left · right |
data-efx-pause | true | Pause on hover and keyboard focus. |
data-efx-gap | 32 | Space between items in px. |
| CSS variable | Default | Controls |
|---|---|---|
--efx-gap | set from data-efx-gap | Space between items. |
path
1.5 KBAn 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.
| Class | What it does |
|---|---|
efx-path | Container. Give it data-efx-svg (an existing svg/path) or data-efx-d (path data, drawn for you). |
efx-path__item | Child that travels the path (several are spaced by data-efx-gap). Its center sits on the path. |
| Attribute | Default | Values |
|---|---|---|
data-efx-mode | scroll | scroll = progress of the container through the viewport · loop = repeat every duration · view = play once when seen. |
data-efx-d | Path data to draw inside an svg the feature creates, scaled to the container. | |
data-efx-viewbox | 0 0 1000 300 | viewBox for data-efx-d; the container gets this aspect ratio if it has no height. |
data-efx-svg | Selector of an existing <svg> or <path> to follow instead of data-efx-d. | |
data-efx-duration | 4000 | ms per trip (loop and view). |
data-efx-rotate | true | Rotate the item to the path tangent. |
data-efx-show-path | true | Draw the path with a trail that grows behind the leading item. |
data-efx-start | 0 | Where on the path (0–1) the trip begins. |
data-efx-end | 1 | Where on the path (0–1) the trip ends. |
data-efx-gap | 0.08 | Spacing between multiple items, as a fraction of the path. |
| CSS variable | Default | Controls |
|---|---|---|
--efx-color | var(--sh-primary) | Trail color. |
odometer
1.0 KBRolling 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.
| Class | What it does |
|---|---|
efx-odometer | Element whose text is the final number. Non-digits ($ , % .) stay static. |
| Attribute | Default | Values |
|---|---|---|
data-efx-duration | 1800 | Roll time in ms. |
data-efx-from | Start value (empty = zeros). | |
data-efx-stagger | 60 | Delay between digits in ms. |
data-efx-once | true | false = reset and replay when re-entering the viewport. |
| CSS variable | Default | Controls |
|---|---|---|
--efx-odo-duration | 1800ms | Set from data-efx-duration. |
parallax
0.7 KBMoves an element slower, faster or opposite to the scroll. Only computes while visible; static with reduced motion.
The gradient layer moves behind this text.
| Class | What it does |
|---|---|
efx-parallax | Shift this element (or its background image with data-efx-bg) as the page scrolls. |
| Attribute | Default | Values |
|---|---|---|
data-efx-speed | 0.3 | Strength, -1 to 1. Negative moves against the scroll. |
data-efx-axis | y | y · x |
data-efx-bg | false | Move the CSS background-image through an injected oversized layer instead of the element. |
reveal
1.6 KBFades, slides, zooms or blurs elements in as they enter the viewport. Content stays visible without JS.
| Class | What it does |
|---|---|
efx-reveal | Animate this element in when it scrolls into view. |
efx-stagger | Container: cascades the delay of every .efx-reveal inside it. |
| Attribute | Default | Values |
|---|---|---|
data-efx-reveal | fade-up | fade · fade-up · fade-down · slide-left · slide-right · zoom · blur · flip · wipe-up · wipe-left · wipe-right · rise · scale-down |
data-efx-delay | 0 | Extra delay in ms. |
data-efx-once | true | false = hide again when it leaves the viewport. |
data-efx-threshold | 0.15 | How far into the viewport (0–1) before it plays. |
data-efx-stagger | 80 | On .efx-stagger: ms between children. |
data-efx-from | first | On .efx-stagger: where the cascade starts: first · last · center · edges · random · or an item index (0-based). |
data-efx-grid | On .efx-stagger: "cols,rows" (e.g. "4,3") or "auto" (measures item positions) to delay by 2D distance from the origin. | |
data-efx-axis | On .efx-stagger with a grid: x or y to measure distance on one axis only. | |
data-efx-ease | linear | On .efx-stagger: easing name (see Effix.add("easing")) distributing the delays along a curve. |
data-efx-total | On .efx-stagger: spread the cascade across this many ms in total instead of ms per step. |
| CSS variable | Default | Controls |
|---|---|---|
--efx-duration | 700ms | Animation length. |
--efx-ease | cubic-bezier(.22,1,.36,1) | Easing. |
--efx-distance | 24px | Travel distance for fade/slide. |
| Kind | Signature | What 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. |
progress
0.6 KBA 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.
| Class | What it does |
|---|---|
efx-progress | The bar element. Fixed to the top by default. |
| Attribute | Default | Values |
|---|---|---|
data-efx-target | "" | CSS selector of an article to measure instead of the whole page. |
data-efx-position | top | top · bottom · none (none = you position it). |
data-efx-height | 4 | Bar thickness in px. |
| CSS variable | Default | Controls |
|---|---|---|
--efx-color | var(--sh-tone, --sh-primary) | Bar color (Shine .tone-* classes work). |
--efx-progress | 0..1 | Set by JS; use it to style anything else. |
scrub
0.9 KBTies transforms, opacity and blur to how far an element has travelled through the viewport. Works on buttons, images, sections, anything. Neutral with reduced motion.
| Class | What it does |
|---|---|
efx-scrub | Scrub this element with scroll. Progress is 0 as it enters at the bottom and 1 as it leaves at the top. |
| Attribute | Default | Values |
|---|---|---|
data-efx-x | 0 | Horizontal travel in px (neutral to value). |
data-efx-y | 0 | Vertical travel in px. |
data-efx-rotate | 0 | End rotation in degrees. |
data-efx-scale | 1 | End scale. |
data-efx-opacity | -1 | End opacity (0–1). -1 leaves opacity alone. |
data-efx-blur | 0 | End blur in px. |
data-efx-from | Advanced start state, e.g. "y:60 opacity:0 scale:.8". Keys: x y rotate scale opacity blur. | |
data-efx-to | Advanced end state, same keys. Overrides the single options. | |
data-efx-start | 0 | Progress (0–1) where the scrub begins. |
data-efx-end | 1 | Progress (0–1) where it finishes. |
data-efx-peak | none | center = 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-ease | linear | linear · ease-in · ease-out · ease-in-out · ease-out-cubic · back-out · elastic-out (in/out/inout aliases), or any registered easing |
| CSS variable | Default | Controls |
|---|---|---|
--efx-p | 0 | Written on the element: eased progress 0–1. Use it in your own CSS calc(). |
| Kind | Signature | What it is |
|---|---|---|
easing | (t: 0..1) => number | Shared 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>sequence
1.5 KBPlays 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.
| Class | What it does |
|---|---|
efx-sequence | A div (image sequence) or a video (scrubbed by currentTime). Becomes a tall scroll track with a pinned stage. |
| Attribute | Default | Values |
|---|---|---|
data-efx-src | Frame URL template with {i}, e.g. frames/f{i}.webp. | |
data-efx-frames | 0 | Number of frames when using src. |
data-efx-pad | 0 | Zero-pad the frame number to this many digits. |
data-efx-start | 1 | First frame number. |
data-efx-list | Alternative to src: frame URLs separated by |. | |
data-efx-height | 300 | Scroll length of the section in vh. |
data-efx-fit | cover | cover · contain |
scrollspy
0.8 KBHighlights the table-of-contents link whose section is in view and optionally smooth-scrolls on click.
| Class | What it does |
|---|---|
efx-scrollspy | Nav/TOC containing a[href^="#"] links. The active link gets is-active and aria-current="true". |
| Attribute | Default | Values |
|---|---|---|
data-efx-offset | 80 | Px from the top where a section becomes active (also scroll offset on click). |
data-efx-active-class | is-active | Class added to the active link. |
data-efx-smooth | true | Smooth scroll on click (respects reduced motion). |
stack
0.4 KBCards stick near the top and pile up as you scroll; each covered card scales back and dims. Plain sticky cards with reduced motion.
Scroll on.
Covers the first.
And the second.
| Class | What it does |
|---|---|
efx-stack | Container. Every direct child becomes a sticky card. |
| Attribute | Default | Values |
|---|---|---|
data-efx-offset | 80 | Sticky top of the first card in px (clear your header). |
data-efx-gap | 16 | Extra top px per card so edges peek out. |
data-efx-shrink | 0.05 | Scale lost per card stacked on top of it. |
data-efx-blur | 0 | Max blur in px for covered cards. |
data-efx-dim | 0.15 | Max darkening (0–1) for covered cards. |
sticky
0.7 KBMakes an element position: sticky and adds state classes: is-stuck (with shadow), is-hidden (hide on scroll down) and is-shrunk.
| Class | What it does |
|---|---|
efx-sticky | Sticky element. Gets is-stuck, is-hidden, is-shrunk. |
| Attribute | Default | Values |
|---|---|---|
data-efx-offset | 0 | Distance from the top edge in px. |
data-efx-hide | false | Hide when scrolling down, show when scrolling up. |
data-efx-shrink | false | Add is-shrunk after scrolling past shrinkAt. |
data-efx-shrink-at | 80 | Scroll distance in px for is-shrunk. |
draw
0.8 KBDraws SVG strokes in, either scrubbed by scroll or played once when visible. Fully drawn without JS or with reduced motion.
| Class | What it does |
|---|---|
efx-draw | On an <svg>, or a container holding one. Paths, lines, circles, rects… are drawn (or only [data-efx-draw-item] ones). |
| Attribute | Default | Values |
|---|---|---|
data-efx-mode | scroll | scroll (tied to scroll progress) · view (plays once when visible). |
data-efx-duration | 1500 | View mode: draw time in ms. |
data-efx-start | 0 | Scroll mode: progress (0–1) where drawing begins. |
data-efx-end | 0.7 | Scroll mode: progress (0–1) where drawing finishes. |
data-efx-stagger | 0 | Per-shape offset: ms in view mode, progress fraction in scroll mode. |
data-efx-fill | false | Fade the fill in at the end of the drawing. |
glitch
0.7 KBRGB-split glitch effect for headings using clipped, offset copies of the text. Static under reduced motion.
| Class | What it does |
|---|---|
efx-glitch | Glitching text (always, or on hover with data-efx-trigger="hover"). |
| Attribute | Default | Values |
|---|---|---|
data-efx-trigger | always | always · hover (also on keyboard focus). |
data-efx-text | Override the glitch layer text (default: the element text). |
| CSS variable | Default | Controls |
|---|---|---|
--efx-glitch-a | Shine accent | First split color. |
--efx-glitch-b | Shine secondary | Second split color. |
--efx-glitch-speed | 2.4s | Cycle length. |
--efx-glitch-bg | transparent | Background of glitch layers (set to the surface color to mask the original). |
kinetic
1.4 KBKinetic 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.
| Class | What it does |
|---|---|
efx-kinetic | Container. Words come from data-efx-words (or the element text). |
| Attribute | Default | Values |
|---|---|---|
data-efx-words | Words or phrases separated by |. | |
data-efx-beat | 600 | Milliseconds per word. |
data-efx-styles | punch|slide|spin|blur|split | Entrance styles, cycled in order. |
data-efx-random | false | Pick styles at random instead of cycling. |
data-efx-colors | Per-word colors separated by |; defaults to Shine tones. | |
data-efx-hold | false | true = stop on the last word instead of looping. |
morph
0.9 KBCycles 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.
| Class | What it does |
|---|---|
efx-morph | Inline element whose text morphs. Without data-efx-words the existing text is used (static). |
| Attribute | Default | Values |
|---|---|---|
data-efx-words | (none) | Words separated by |, e.g. Design|Build|Ship. |
data-efx-duration | 1200 | Morph time in ms. |
data-efx-pause | 1800 | Hold time between morphs in ms. |
| CSS variable | Default | Controls |
|---|---|---|
--efx-morph-justify | center | Alignment of shorter words inside the reserved width (start | center | end). |
proximity
1.2 KBLetters or icons scale, thicken, lift and recolor depending on how close the pointer is, like a macOS dock. Fine pointers and motion-OK only.
| Class | What it does |
|---|---|
efx-proximity | Text is split into letters (screen readers get the original); with data-efx-mode="items" children marked [data-efx-item] react instead. |
efx-proximity__c | Injected letter span. |
| Attribute | Default | Values |
|---|---|---|
data-efx-radius | 120 | Distance in px within which pieces react. |
data-efx-scale | 1.4 | Scale of the closest piece. |
data-efx-weight | 0 | Target font-weight at the pointer (0 = off). Needs a variable font to look smooth. |
data-efx-lift | 0 | Upward lift in px. |
data-efx-color | Color to mix in near the pointer (empty = off), e.g. var(--sh-primary). | |
data-efx-mode | letters | letters · items |
sparkles
0.9 KBTwinkling 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.
| Class | What it does |
|---|---|
efx-sparkles | Host element. Sparkles are drawn in an overlay (no pointer events) that may overflow the element a little. |
| Attribute | Default | Values |
|---|---|---|
data-efx-count | 10 | Number of stars (max 60). |
data-efx-color | (theme + gold) | One color or a list separated by |. |
data-efx-size-min | 8 | Smallest star in px. |
data-efx-size-max | 18 | Largest star in px. |
data-efx-speed | 1 | Twinkle speed multiplier. |
data-efx-shape | star | Name of a registered sparkle-shape. |
| CSS variable | Default | Controls |
|---|---|---|
--efx-color | Shine tone / primary | Used for the first color when data-efx-color is empty. |
| Kind | Signature | What it is |
|---|---|---|
sparkle-shape | fn(size) -> svg markup string or Node | Draw 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
0.9 KBSplits 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.
| Class | What it does |
|---|---|
efx-split | Element whose text is split and animated. Inline markup inside is flattened. |
| Attribute | Default | Values |
|---|---|---|
data-efx-by | word | word · letter (falls back to word above max pieces). |
data-efx-effect | fade-up | fade · fade-up · blur · slide · wave (looping). |
data-efx-stagger | 40 | Delay between pieces in ms. |
data-efx-duration | 600 | Per-piece animation time in ms. |
data-efx-once | true | false = replay when re-entering the viewport. |
data-efx-max | 200 | Max letters to split; beyond this, split by word. |
| CSS variable | Default | Controls |
|---|---|---|
--efx-ease | cubic-bezier(.22,1,.36,1) | Easing. |
textfill
1.0 KBApple-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.
| Class | What it does |
|---|---|
efx-textfill | Element whose text is split into pieces that fill in with scroll. |
| Attribute | Default | Values |
|---|---|---|
data-efx-start | 0.8 | Viewport fraction (from top) where the element top starts the fill. |
data-efx-end | 0.3 | Viewport fraction where the element bottom finishes the fill. |
data-efx-by | word | word · letter. |
data-efx-dim | 0.2 | Opacity of unfilled text. |
data-efx-color | Text color once filled (default: current color). |
| CSS variable | Default | Controls |
|---|---|---|
--efx-textfill-dim | 0.2 | Opacity of unfilled text. |
--efx-textfill-color | currentColor | Filled text color. |
scramble
0.9 KBDecodes 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.
Build faster
| Class | What it does |
|---|---|
efx-scramble | Scramble this element's text (headings, spans, buttons). |
| Attribute | Default | Values |
|---|---|---|
data-efx-trigger | view | view · hover · load · click. |
data-efx-chars | !<>-_\/[]{}—=+*^?#________ | Glyph pool used while scrambling. |
data-efx-speed | 30 | Milliseconds per frame. |
data-efx-duration | 900 | Total decode time in ms. |
data-efx-once | true | false = replay each time it re-enters the viewport. |
data-efx-words | a|b|c : cycle through these phrases like a rotating headline. | |
data-efx-pause | 2000 | Words mode: ms to hold each phrase. |
typed
0.9 KBTypewriter or rotating words with a blinking cursor. Screen readers get the first word; reduced motion shows it statically.
| Class | What it does |
|---|---|
efx-typed | Inline element whose text rotates through data-efx-words. |
| Attribute | Default | Values |
|---|---|---|
data-efx-words | Words separated by | or ,. | |
data-efx-speed | 60 | Typing speed, ms per character. |
data-efx-back | 30 | Deleting speed, ms per character. |
data-efx-pause | 1600 | Hold time per word in ms. |
data-efx-loop | true | false = stop on the last word. |
data-efx-cursor | true | Show blinking cursor. |
data-efx-mode | type | type · fade · slide (fade/slide swap whole words). |
border
1.5 KBSpinning, tracing, glowing or shifting gradient borders for buttons, cards or anything. Optional loading mode driven by clicks.
| Class | What it does |
|---|---|
efx-border-spin | Rotating conic-gradient ring. |
efx-border-trace | A short comet segment travelling around the border (loading indicator). |
efx-border-glow | Gradient ring with a pulsing glow. |
efx-border-gradient | Slowly shifting linear gradient border. |
efx-border-wipe | Border draws itself around the edges on hover / keyboard focus (straight edges). |
efx-border-pulse | Expanding ring pulse radiating from the element (loops). |
| Attribute | Default | Values |
|---|---|---|
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-speed | 0 | Seconds per cycle; 0 = CSS default (3s). |
data-efx-width | 0 | Border width in px; 0 = CSS default (2px). |
data-efx-loading | "" = always animate · click = animate only while loading (after a click) · always. | |
data-efx-timeout | 0 | With loading=click: auto-stop after ms (0 = until efx:done). |
| CSS variable | Default | Controls |
|---|---|---|
--efx-border-colors | primary, accent, secondary | Comma list of gradient colors. |
--efx-border-color | var(--sh-tone, --sh-primary) | Single color for trace and glow. |
--efx-border-width | 2px | Ring thickness. |
--efx-border-speed | 3s | Cycle duration. |
--efx-border-radius | inherit | Ring radius (inherits Shine button/card radius). |
confetti
1.3 KBConfetti 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.
| Class | What it does |
|---|---|
efx-confetti | Burst confetti from this element. |
| Attribute | Default | Values |
|---|---|---|
data-efx-trigger | click | click · view · done (efx:done from border loading, copy, countdown). |
data-efx-count | 80 | Particles per burst. |
data-efx-spread | 70 | Fan angle in degrees (centered upward). |
data-efx-velocity | 45 | Launch speed. |
data-efx-gravity | 1 | Gravity multiplier. |
data-efx-colors | red|#0af|… (default: Shine primary, accent, success, warning, danger). | |
data-efx-shapes | square|circle|strip | square · circle · strip, or any registered confetti-shape. |
data-efx-origin | "x% y%" of the viewport; empty = pointer / element center. |
| Kind | Signature | What it is |
|---|---|---|
confetti-shape | (ctx, size, piece) => void | Paint 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
2.7 KBAnimated 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.
Move the pointer: the orbs drift toward it.
| Class | What it does |
|---|---|
efx-ambient | Injects a canvas behind the content (content stays clickable and above). Pick the look with data-efx-mode. |
| Attribute | Default | Values |
|---|---|---|
data-efx-mode | stars | stars · 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-count | 0 | Number 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-speed | 1 | Speed multiplier. |
data-efx-opacity | 1 | Overall opacity (0–1). |
data-efx-interact | true | Stars, warp, orbs and grid react to the pointer (fine pointers only). false = ignore the pointer. |
| CSS variable | Default | Controls |
|---|---|---|
--efx-color | Shine tone / primary | Color when data-efx-color is empty. |
| Kind | Signature | What 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>globe
1.2 KBA 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.
| Class | What it does |
|---|---|
efx-globe | Host. Square by default (aspect-ratio 1): set a width or max-width. The canvas fills it. |
| Attribute | Default | Values |
|---|---|---|
data-efx-dots | 1200 | Number of dots on the sphere. |
data-efx-speed | 0.2 | Auto-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-tilt | 0.3 | Initial axis tilt in radians. |
data-efx-drag | true | Drag with the pointer to rotate. |
| CSS variable | Default | Controls |
|---|---|---|
--efx-color | Shine tone / primary | Color when data-efx-color is empty. |
particles
1.8 KBDrifting canvas particles behind any section, optionally linked by lines and reacting to the pointer. Pauses off-screen and in hidden tabs.
Move the pointer over this area.
| Class | What it does |
|---|---|
efx-particles | Injects a canvas behind the content (content stays clickable and above). |
| Attribute | Default | Values |
|---|---|---|
data-efx-count | 50 | Max 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-min | 1 | Smallest radius in px. |
data-efx-size-max | 2.8 | Largest radius in px. |
data-efx-speed | 100 | Speed in percent. |
data-efx-opacity | 1 | Particle opacity (0–1). |
data-efx-links | false | Draw lines between nearby particles. |
data-efx-link-distance | 110 | Max link length in px. |
data-efx-interact | repel | none · repel · attract · connect (pointer joins the network). |
data-efx-interact-radius | 120 | Pointer influence radius in px. |
data-efx-shape | circle | circle · square · triangle · star · heart, a list like circle|star, or any registered particle-shape. |
| CSS variable | Default | Controls |
|---|---|---|
--efx-color | Shine tone / primary | Particle color when data-efx-color is empty. |
| Kind | Signature | What it is |
|---|---|---|
particle-shape | (ctx2d, size, particle) => void | Build 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>trail
1.6 KBImages, 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
| Class | What it does |
|---|---|
efx-trail | Section that shows the trail / hover preview (becomes position:relative if static). |
efx-trail__item | Injected, pooled, aria-hidden trail node. |
| Attribute | Default | Values |
|---|---|---|
data-efx-images | a.jpg|b.jpg|c.jpg : images to spawn (random pick). | |
data-efx-spacing | 80 | Pointer distance in px between spawns. |
data-efx-life | 900 | Lifetime of each item in ms. |
data-efx-size | 140 | Item size in px (preview width in hover mode). |
data-efx-rotate | 12 | Random rotation +/- degrees. |
data-efx-max | 12 | Pool size (items alive at once). |
data-efx-shape | Without images: dot · ring · emoji:✨ · or name[:arg] of any registered trail-shape | |
data-efx-mode | trail | trail · hover (floating preview of the hovered [data-efx-image]). |
data-efx-image | On a child in hover mode: preview image URL. |
| CSS variable | Default | Controls |
|---|---|---|
--efx-color | Shine tone/primary | Color for dot and ring shapes. |
| Kind | Signature | What it is |
|---|---|---|
trail-shape | (size, arg) => Node | Return 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>cursor
1.1 KBA 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.
| Class | What it does |
|---|---|
efx-cursor | On <body> (page-wide) or any container to enable the custom cursor. |
efx-cursor-hover | Mark extra elements that should trigger the hover state. |
efx-cursor-hide | Added automatically with data-efx-hide-native (cursor:none). |
| Attribute | Default | Values |
|---|---|---|
data-efx-style | ring | ring · dot · dot-ring |
data-efx-size | 32 | Ring diameter in px. |
data-efx-color | (theme) | Cursor color. |
data-efx-hide-native | false | Hide the native cursor. |
data-efx-blend | false | mix-blend-mode: difference. |
data-efx-hover | a,button,[role=button],input,select,textarea,label,summary,.efx-cursor-hover | Selector that triggers the hover state. |
| CSS variable | Default | Controls |
|---|---|---|
--efx-cursor-color | theme | Set on the injected cursor elements. |
--efx-cursor-size | size option | Set on the injected cursor elements. |
dim
1.2 KBHover 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.
| Class | What it does |
|---|---|
efx-dim | List/grid container. Its children (or data-efx-items) dim while one is hovered or focused. |
is-hovered | Added to the active child, handy for an expand/underline style of your own. |
| Attribute | Default | Values |
|---|---|---|
data-efx-opacity | 0.35 | Opacity of the dimmed siblings. |
data-efx-blur | 0 | Blur in px for dimmed siblings. |
data-efx-preview | true | Show a floating image following the cursor when the item has data-efx-image (fine pointers only). |
data-efx-items | CSS selector for the items. Default: direct children. |
| CSS variable | Default | Controls |
|---|---|---|
--efx-dim-opacity | 0.35 | Dimmed opacity (also set by data-efx-opacity). |
--efx-dim-blur | 0px | Dimmed blur. |
--efx-dim-gray | 0 | Grayscale amount 0 to 1 for dimmed items. |
--efx-dim-size | 220px | Preview width. |
direction
0.9 KBDetects 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.
Enter and leave from different sides.
Keyboard focus fills from the left.
Floods from where the pointer enters.
| Class | What it does |
|---|---|
efx-direction | Sets data-efx-from (top | right | bottom | left) and .is-hover; adds the sliding fill overlay. |
| Attribute | Default | Values |
|---|---|---|
data-efx-fill | edge | edge = 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 variable | Default | Controls |
|---|---|---|
--efx-x / --efx-y | pointer % | Written in circle mode: the entry/exit point the circle grows from. |
--efx-direction-color | Shine primary 15% | Fill color. |
--efx-direction-duration | 280ms | Slide duration. |
draggable
1.8 KBDrag 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
| Class | What it does |
|---|---|
efx-draggable | Make this element draggable. It moves with the `translate` property (not `transform`), is focusable and gets role="group" + aria-roledescription="draggable". |
| Attribute | Default | Values |
|---|---|---|
data-efx-axis | both | x · y · both |
data-efx-bounds | parent | "parent", a CSS selector of a bounding element, or "none". |
data-efx-release | spring | spring = snap back to the start · inertia = keep gliding with friction · stay = leave it where dropped. |
data-efx-spring | 170,18 | Spring "stiffness,damping". |
data-efx-friction | 0.92 | Inertia: velocity kept per frame (closer to 1 = longer glide). |
data-efx-bounce | 0.5 | Inertia: speed kept when bouncing off a bound (0 = dead stop). |
data-efx-snap | 0 | Grid size in px to snap to (0 = off). |
data-efx-step | 10 | Arrow-key step in px (Shift = ×5; the snap size wins when set). |
data-efx-handle | Selector inside the element that starts the drag (touch-action:none is set on the handle only). |
| CSS variable | Default | Controls |
|---|---|---|
--efx-color | Shine tone/primary | Focus ring color. |
| Event | When |
|---|---|
efx:dragstart | Fired once the pointer has moved a few pixels. detail = {x, y}. |
efx:drag | On every move (and arrow-key nudge). detail = {x, y} translate offsets. |
efx:dragend | On pointer release, before the spring/inertia plays. detail = {x, y}. |
magnetic
0.6 KBPulls a button or element toward the pointer as it approaches, then springs back. Fine pointers and motion-OK only.
| Class | What it does |
|---|---|
efx-magnetic | Make this element magnetic. |
| Attribute | Default | Values |
|---|---|---|
data-efx-strength | 0.3 | Fraction of the pointer offset applied. |
data-efx-radius | 120 | Activation distance (px) beyond the element edge. |
data-efx-max | 24 | Max displacement in px. |
| CSS variable | Default | Controls |
|---|---|---|
--efx-mx / --efx-my | set by JS | Current offset. |
mouse
0.8 KBLayered 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.
| Class | What it does |
|---|---|
efx-mouse | Container whose layers follow the pointer. |
| Attribute | Default | Values |
|---|---|---|
data-efx-strength | 20 | Max shift in px at depth 1. |
data-efx-scope | self | self = pointer inside the container · page = pointer anywhere in the viewport. |
data-efx-invert | false | Move with the pointer instead of against it. |
data-efx-rotate | 0 | Max rotateZ in degrees per layer. |
data-efx-ease | 0.12 | Smoothing per frame (0.01 slow – 1 instant). |
data-efx-gyro | false | Touch devices: drive the layers from device tilt. Never prompts; on iOS it only works if your page already obtained motion permission. |
data-efx-depth | On a child layer: multiplier of strength (e.g. 0.2 far, 1 near, negative = opposite). |
ripple
0.7 KBMaterial-style click ripple for buttons and cards. Enter/Space ripple from the centre. Disabled under reduced motion.
| Class | What it does |
|---|---|
efx-ripple | Adds position:relative, overflow:hidden and the click ripple. |
| Attribute | Default | Values |
|---|---|---|
data-efx-color | (currentColor 25%) | Ripple color. |
data-efx-duration | 600 | Duration in ms. |
data-efx-center | false | Always ripple from the centre. |
| CSS variable | Default | Controls |
|---|---|---|
--efx-ripple-color | currentColor 25% | Ripple color. |
--efx-ripple-dur | 600ms | Duration. |
spotlight
0.7 KBA radial glow that follows the pointer inside a card or section, optionally lighting the border too. Fine pointers only.
Move the pointer around.
Border glows too.
| Class | What it does |
|---|---|
efx-spotlight | Add the pointer-following glow to this element. |
efx-spotlight--border | Added automatically with data-efx-border. |
| Attribute | Default | Values |
|---|---|---|
data-efx-size | 240 | Glow radius in px. |
data-efx-color | (theme) | Glow color. Empty = Shine tone/primary. |
data-efx-opacity | 0.18 | Glow strength (0–1). |
data-efx-border | false | Also light the border. |
| CSS variable | Default | Controls |
|---|---|---|
--efx-x / --efx-y | set by JS | Pointer position inside the element. |
--efx-color | Shine tone / primary | Glow color fallback. |
tilt
1.0 KB3D tilt toward the pointer with optional glare. Fine pointers and motion-OK only.
Hover me.
Stronger tilt.
| Class | What it does |
|---|---|
efx-tilt | Tilt this element toward the pointer. |
efx-tilt__glare | Injected glare layer (data-efx-glare). |
| Attribute | Default | Values |
|---|---|---|
data-efx-max | 10 | Max rotation in degrees. |
data-efx-perspective | 900 | Perspective in px. |
data-efx-scale | 1.02 | Scale while hovered. |
data-efx-glare | false | Add a light glare following the pointer. |
data-efx-reset | true | Ease back to flat when the pointer leaves. |
data-efx-gyro | false | Touch devices: tilt with the phone (deviceorientation). Never prompts; on iOS it only works if your page already obtained motion permission. |
| CSS variable | Default | Controls |
|---|---|---|
--efx-rx / --efx-ry | set by JS | Current rotation (read-only in practice). |
beam
1.2 KBAnimated 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.
| Class | What it does |
|---|---|
efx-beam | Container holding the nodes. Draws an overlay SVG (no pointer events) with one beam per link. |
| Attribute | Default | Values |
|---|---|---|
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-curvature | 40 | Curve height in px (0 = straight line, negative bends downward). |
data-efx-speed | 3 | Seconds for a beam to travel its path. |
data-efx-width | 2 | Stroke width in px. |
data-efx-color | (Shine primary to accent) | Solid CSS color. Empty = gradient from --sh-primary to --sh-accent. |
data-efx-reverse | false | Travel from the second element to the first. |
| CSS variable | Default | Controls |
|---|---|---|
--sh-primary | #6366f1 | Gradient start (Shine token). |
--sh-accent | #ec4899 | Gradient end (Shine token). |
divider
2.2 KBAnimated SVG dividers (waves, clouds, mountains, drips…) generated inline and colored to match the neighbouring section.
| Class | What it does |
|---|---|
efx-divider | Placeholder 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. |
| Attribute | Default | Values |
|---|---|---|
data-efx-shape | wave | wave · waves · tilt · curve · triangle · arrow · zigzag · clouds · mountains · drips · steps · spikes · sawtooth · chevron · swoosh · leaves · hills, or any registered divider-shape |
data-efx-color | Fill color; empty = --efx-divider-color or Shine --sh-bg. | |
data-efx-height | 80 | Height in px. |
data-efx-flip | false | Mirror horizontally. |
data-efx-invert | false | Mirror vertically (for dividers at the top of a section). |
data-efx-animate | none | none · drift (periodic shapes scroll sideways) · layers (3 drifting copies) · float (bob). Non-periodic shapes fall back to float. |
data-efx-speed | 12 | Seconds per drift loop. |
data-efx-path | Custom 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-position | top · bottom = absolutely placed on the parent section edge; empty = normal block. |
| CSS variable | Default | Controls |
|---|---|---|
--efx-divider-color | var(--sh-bg) | Fill color (use the next section's background). |
| Kind | Signature | What 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
2.0 KBMorphs 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).
| Class | What it does |
|---|---|
efx-shape | On an <svg> (a path is generated inside, filled with the Shine tone) or directly on a <path> (keeps your own fill/stroke). |
| Attribute | Default | Values |
|---|---|---|
data-efx-d | Pipe-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-shapes | Pipe-separated selectors of existing geometry (path, circle, rect…), e.g. "#s1|#s2|#s3". Put the sources in <defs>. | |
data-efx-to | On a <path>: target path data. Morphs from the path's own d (pipe-separate for more). | |
data-efx-points | 64 | Samples per shape. More = smoother, heavier. |
data-efx-trigger | loop | loop (cycle all shapes) · hover (first -> second on hover/focus) · scroll (progress through the viewport) |
data-efx-duration | 1200 | Morph time in ms. |
data-efx-pause | 800 | loop: hold time between morphs in ms. |
data-efx-ease | ease-in-out | Easing name (see Effix.add("easing")). |
data-efx-target | hover: selector of the element that listens (default: the closest link/button, else the shape). |
| CSS variable | Default | Controls |
|---|---|---|
--efx-color | Shine tone/primary | Fill of the generated path. |
| Kind | Signature | What it is |
|---|---|---|
Effix.add | 'shape', name, d | Register 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'));feed
0.8 KBAn 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.
| Class | What it does |
|---|---|
efx-feed | Container. Its direct children are the feed items (cards, rows, anything). Add .stack or a flex column for spacing. |
| Attribute | Default | Values |
|---|---|---|
data-efx-interval | 1500 | Milliseconds between new items. |
data-efx-max | 4 | How many items are visible at once (the oldest leaves when exceeded). |
data-efx-loop | true | Start over after the last item. false = stop once all have appeared. |
data-efx-order | newest | newest = new items enter at the top · append = enter at the bottom. |
audio
2.3 KBAudio-reactive canvas visualizer (bars, wave, circle, scope, dots) for an
| Class | What it does |
|---|---|
efx-audio | The visualizer box (give it a height). Injects a canvas; may also contain the media element. |
efx-audio__canvas | Injected canvas (aria-hidden, pointer-events none). |
| Attribute | Default | Values |
|---|---|---|
data-efx-for | (audio/video inside) | Selector of the media element, e.g. #song. |
data-efx-type | bars | bars · 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-count | 48 | Number of bars / spokes. |
data-efx-gain | 1 | Multiplier on the --efx-level value. |
| CSS variable | Default | Controls |
|---|---|---|
--efx-level | 0 | Written 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)). |
| Kind | Signature | What it is |
|---|---|---|
audio-viz | (ctx2d, { freq, time, level, count }, w, h, colors) => void | Draw 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>compare
1.3 KBDrag a handle to reveal the second image over the first. Keyboard and screen reader friendly via a hidden range input.
| Class | What it does |
|---|---|
efx-compare | Container with exactly two <img> children: before, then after. Gets .is-dragging while dragging. |
| Attribute | Default | Values |
|---|---|---|
data-efx-start | 50 | Starting position, percent. |
data-efx-vertical | false | Split top/bottom instead of left/right. |
data-efx-hover | false | Follow the mouse without dragging (fine pointers only). |
| CSS variable | Default | Controls |
|---|---|---|
--efx-pos | 50% | Current split position (set by JS). |
--efx-handle | var(--sh-bg) | Handle line color. |
carousel
1.9 KBAdds arrows, dots, keyboard, accessible autoplay and an optional fade mode to Shine's scroll-snap .carousel.
| Class | What it does |
|---|---|
efx-carousel | Add next to Shine's .carousel (the track itself). Children are the slides; the active ones get .is-active. Add tabindex="0" for ←/→ keys. |
efx-carousel__nav | Generated after the track: prev/next buttons, dots and a pause button when autoplay is on. |
| Attribute | Default | Values |
|---|---|---|
data-efx-autoplay | 0 | Ms between slides. 0 = off. Pauses on hover, focus, offscreen, and via a pause button. Ignored with reduced motion. |
data-efx-loop | true | Wrap around at the ends. |
data-efx-dots | true | Show dot navigation. |
data-efx-arrows | true | Show prev/next buttons. |
data-efx-per-view | 0 | Slides visible at once. 0 = respect CSS (e.g. .carousel-peek). |
data-efx-fade | false | Crossfade stacked slides instead of scrolling (hero sliders). |
| CSS variable | Default | Controls |
|---|---|---|
--efx-per-view | (unset) | Slides per view, set when per-view is > 0. |
copy
0.6 KBCopies an element's text (or a literal) to the clipboard, swaps the label and announces it to screen readers.
npm install effix
| Class | What it does |
|---|---|
efx-copy | Add to a button. Gets .is-copied while the done label shows. |
| Attribute | Default | Values |
|---|---|---|
data-efx-target | CSS selector of the element to copy. Inputs/textareas use their value, others textContent. | |
data-efx-text | Literal text to copy (wins over target). | |
data-efx-done | Copied! | Label shown after copying. |
data-efx-duration | 1800 | Ms before the label reverts. |
drag
0.7 KBClick-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.
| Class | What it does |
|---|---|
efx-drag | Container with overflow: auto/scroll. Gets grab/grabbing cursors and .is-dragging while dragging. |
| Attribute | Default | Values |
|---|---|---|
data-efx-inertia | true | Keep gliding after release (friction 0.95). Off with reduced motion. |
data-efx-axis | x | x · y · both |
zoom
0.9 KBHover 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.
| Class | What it does |
|---|---|
efx-zoom | Wrapper around an <img>. Add data-efx-full="large.jpg" on the img (or wrapper) for a sharper zoom source. |
| Attribute | Default | Values |
|---|---|---|
data-efx-scale | 2.5 | Magnification factor. |
data-efx-size | 160 | Lens diameter in px (circle and square). |
data-efx-shape | circle | circle · square · inner (whole image zooms in place, following the pointer). |
layout
2.1 KBAnimates 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").
| Class | What it does |
|---|---|
efx-layout | Container 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-tags | On a child: space-separated tags used by the filter. |
| Attribute | Default | Values |
|---|---|---|
data-efx-duration | 400 | Animation length in ms. |
data-efx-ease | cubic-bezier(.22,1,.36,1) | CSS easing string (cubic-bezier, ease-out, linear(…)). |
data-efx-scale | 0.9 | Scale entering items start from / leaving items shrink to. |
data-efx-noun | item | Word used in the live count ("6 items"). |
data-efx-count | Selector of your own element to receive the count (it gets aria-live="polite"); otherwise a hidden status node is added after the container. |
| CSS variable | Default | Controls |
|---|---|---|
--efx-color | Shine tone/primary | Outline of the pressed filter/sort buttons. |
lazyimg
0.5 KBBlur-up image loading: a tiny placeholder shows first, the full image loads when near the viewport and sharpens in. Works for and background images.
| Class | What it does |
|---|---|
efx-lazyimg | On an <img> (data-efx-src / data-efx-srcset) or any element with data-efx-bg. |
is-lazy / is-loaded / is-error | State classes set by JS. |
| Attribute | Default | Values |
|---|---|---|
data-efx-margin | 300px | How early to start loading (rootMargin). |
data-efx-blur | 12 | Blur radius in px of the placeholder. |
data-efx-src | Full image URL (img). | |
data-efx-srcset | Full srcset (img); optional data-efx-sizes. | |
data-efx-bg | Full background image URL (any element). |
| CSS variable | Default | Controls |
|---|---|---|
--efx-blur | set by JS | Placeholder blur radius. |
lightbox
1.7 KBOpens linked images in one shared Shine modal with captions, prev/next, counter, arrow keys and touch swipe. Links still work without JS.
| Class | What it does |
|---|---|
efx-lightbox | Container of <a href="full.jpg"><img></a> links (or any element with data-efx-src). Caption: data-efx-caption, img alt, or figcaption. |
| Attribute | Default | Values |
|---|---|---|
data-efx-loop | true | Wrap from last to first. |
data-efx-captions | true | Show captions. |
data-efx-group | Containers sharing the same group value form one gallery. |
| CSS variable | Default | Controls |
|---|---|---|
--efx-lb-bg | var(--sh-surface) | Dialog background. |
lyrics
2.0 KBCaptions 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.
| Class | What it does |
|---|---|
efx-lyrics | The lyrics box (scrolls internally; set a height with --efx-lyrics-height). |
efx-lyrics__list | Injected <ol> of lines. |
efx-lyrics__line | Injected <li>; gets aria-current="true" and .is-active while sung. |
efx-lyrics__btn | Injected seek button (a <span> when data-efx-seek="false"). |
efx-lyrics__word | Injected word span in karaoke mode (--p = 0..1 fill). |
| Attribute | Default | Values |
|---|---|---|
data-efx-for | (parent audio/video) | Selector of the media element, e.g. #song. |
data-efx-cues | JSON [{"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-karaoke | false | Fill words progressively (background-clip text gradient). Words without timing are spread evenly over the line. |
data-efx-scroll | true | Auto-scroll the active line to the middle of the box (pauses 3s after you scroll it yourself). |
data-efx-seek | true | Clicking a line sets media.currentTime. |
data-efx-offset | 0 | Seconds added to the media time (lyrics early/late). |
| CSS variable | Default | Controls |
|---|---|---|
--efx-lyrics-height | 16rem | Max height of the box. |
--efx-lyrics-active | var(--sh-primary) | Active line color. |
--efx-lyrics-fill | var(--sh-primary) | Karaoke filled color. |
--efx-lyrics-dim | 45% currentColor | Karaoke unfilled color. |
popup
0.7 KBAuto-opens a Shine modal on a timer, after scrolling, or on exit intent, with frequency capping. Also wires up open/close buttons.
| Class | What it does |
|---|---|
efx-popup | Add 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. |
| Attribute | Default | Values |
|---|---|---|
data-efx-delay | -1 | Seconds before auto-opening. -1 = off. |
data-efx-scroll | 0 | Open after scrolling this percent of the page. 0 = off. |
data-efx-exit | false | Open on exit intent (pointer leaves the top of the window, desktop only). |
data-efx-frequency | always | always · session · days · once. |
data-efx-days | 7 | With frequency="days": wait this many days before showing again. |
data-efx-id | (element id) | Storage key suffix: efx-popup:<id>. |
pricing
1.7 KBMonthly/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.
| Class | What it does |
|---|---|
efx-pricing | Container of the switch and the prices. |
efx-pricing__toggle | Optional checkbox instead of buttons: unchecked = first period, checked = second. |
| Attribute | Default | Values |
|---|---|---|
data-efx-periods | Monthly|Yearly | Period names, in the order of every "|" list below. |
data-efx-start | 0 | Index of the initial period. |
data-efx-duration | 600 | Count tween time in ms (non-odometer prices). |
| Kind | Signature | What 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. |
Event | efx:period | Fires on the container with detail {index, period}. |
schedule
0.8 KBShows 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.
| Class | What it does |
|---|---|
efx-schedule | Gets [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. |
| Attribute | Default | Values |
|---|---|---|
data-efx-from | Start, e.g. 2026-12-01 or 2026-12-01T09:00 (local time). | |
data-efx-until | End (exclusive), e.g. 2026-12-26T00:00. | |
data-efx-days | Weekdays, e.g. mon-fri or sat,sun. | |
data-efx-hours | Daily hours, e.g. 09:00-17:00 (may wrap past midnight). | |
data-efx-mode | show | show = visible inside the window · hide = visible outside it. |
shimmer
1.0 KBLoading 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.
This card was a skeleton for 2.5 seconds.
| Class | What it does |
|---|---|
efx-shimmer | Skeleton block. With data-efx-until / data-efx-for it wraps real content and clears when ready. |
efx-shimmer-text | Shimmering text (gradient sweep clipped to the glyphs). |
efx-shimmer-btn | Button shine sweep (add to .btn). |
efx-skeleton-line | Text-line placeholder. |
efx-skeleton-circle | Avatar placeholder. |
efx-skeleton-rect | Image/card placeholder. |
| Attribute | Default | Values |
|---|---|---|
data-efx-until | Selector of image/element to wait for (load/error event; "efx:ready" event also works). | |
data-efx-for | 0 | Ms to wait, or the timeout when combined with until. |
| CSS variable | Default | Controls |
|---|---|---|
--efx-shimmer-base | var(--sh-surface-2) | Skeleton base color. |
--efx-shimmer-hi | derived | Sweep highlight color. |
--efx-shimmer-duration | 1.6s | Sweep time. |
media
0.8 KBVideos 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.
| Class | What it does |
|---|---|
efx-media | On a <video>, or on a container holding videos. |
efx-media__play | Injected play button (reduced motion, container hosts). |
| Attribute | Default | Values |
|---|---|---|
data-efx-play | view | view = play while visible · hover = play on hover/focus (or add data-efx-hover) · none = lazy src only. |
data-efx-threshold | 0.4 | Visible fraction (0–1) needed before playing. |
data-efx-reset | false | Rewind to the start when paused. |
data-efx-src | On the video or a <source>: URL, assigned only when within ~300px of the viewport. |
collapse
0.7 KBAnimates native
A small JS partner for the Shine CSS framework.
Native details/summary: keyboard and screen readers work as usual.
Opening one closes the other, animated.
No: without JS the accordion toggles natively.
| Class | What it does |
|---|---|
efx-collapse | On a <details>, or a container: every <details> inside is animated. |
| Attribute | Default | Values |
|---|---|---|
data-efx-duration | 300 | Animation time in ms. |
data-efx-easing | ease | Any CSS easing. |
spinner
1.2 KBPure 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.
| Class | What it does |
|---|---|
efx-spinner | Base loader (ring). Choose a variant with data-efx-type or a class. |
efx-spinner-ring / -dots / -bars / -pulse / -orbit / -wave / -square | Variant classes (alternative to data-efx-type). |
| Attribute | Default | Values |
|---|---|---|
data-efx-type | ring · dots · bars · pulse · orbit · wave · square | |
data-efx-label | Loading | Hidden label text for screen readers. |
| CSS variable | Default | Controls |
|---|---|---|
--efx-spinner-size | 2.5rem | Width and height. |
--efx-color | Shine tone/primary | Spinner color. |
toast
1.5 KBNotification 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.
| Class | What it does |
|---|---|
efx-toast | Hidden template whose content becomes the toast. Needs `hidden`. Styled by Shine .toast. |
| Attribute | Default | Values |
|---|---|---|
data-efx-show | (off) | Show automatically after this many ms. |
data-efx-position | bottom-right | top|bottom + left|center|right. |
data-efx-duration | 5000 | Auto-hide ms (0 = sticky). Paused while hovered or focused. |
data-efx-tone | Shine tone (primary, success, danger...). |
| Kind | Signature | What it is |
|---|---|---|
Trigger | [data-efx-toast="#id"] | Clicking shows the template with that id. |
Event | efx:toast | document.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. |
transition
1.3 KBSmooth 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.
| Class | What it does |
|---|---|
efx-transition | Put on <html> or <body> of every page that should animate (use it on all pages, so enter + exit match). |
efx-transition__curtain | Injected overlay used by the JS fallback. |
| Attribute | Default | Values |
|---|---|---|
data-efx-style | fade | fade · slide-up · curtain · zoom |
data-efx-duration | 400 | Animation length in ms. |
data-efx-prefetch | true | Add <link rel=prefetch> when an internal link is hovered or focused. |
data-efx-no-transition | On a link (or ancestor): navigate normally, no animation. |
| CSS variable | Default | Controls |
|---|---|---|
--efx-color | Shine primary | Curtain color (style "curtain"). |
countdown
1.2 KBLive 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.
| Class | What it does |
|---|---|
efx-countdown | Container; renders .efx-countdown__unit > __num + __label. |
| Attribute | Default | Values |
|---|---|---|
data-efx-to | Target date/time, e.g. 2027-01-31T18:00 (local) or with Z. | |
data-efx-units | dhms | Subset of d h m s; larger omitted units roll into the next. |
data-efx-labels | Days|Hours|Minutes|Seconds | Unit labels separated by |. |
data-efx-expired | Text shown when finished; empty = keep zeros. | |
data-efx-pad | true | Zero-pad hours/minutes/seconds. |
data-efx-compact | false | Single line like "3d 04:05:06". |
| CSS variable | Default | Controls |
|---|---|---|
--efx-countdown-bg | var(--sh-surface-2) | Unit card background. |
chart-bar
2.7 KBVertical 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.
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"}.| Class | What it does |
|---|---|
efx-chart-bar | Renders a bar chart from data-efx-data, inline JSON or a table. |
| Attribute | Default | Values |
|---|---|---|
data-efx-data | "12,19,7" · several series "3,5|4,1" · JSON [[3,5],[4,1]] or [{"name":"A","data":[…]}] | |
data-efx-labels | Category labels: "Q1|Q2|Q3". | |
data-efx-names | Series names: "2025|2026". | |
data-efx-source | CSS selector of a Shine table to read (first column = labels). | |
data-efx-horizontal | false | Horizontal bars. |
data-efx-stacked | false | Stack series instead of grouping. |
data-efx-style | bar | <code>lollipop</code> draws a stick and a dot instead of a bar. |
data-efx-radial | false | Circular barplot: bars radiate from an inner circle, labels around the ring (works stacked or grouped). |
data-efx-normalize | false | 100% stacked: every category is scaled to 100% (tooltip shows % and raw value). |
data-efx-diverging | false | Negative values extend left/down from a centred zero line; with one series negatives use the danger colour. |
data-efx-values | false | Print values on the bars. |
data-efx-radius | 4 | Bar corner radius. |
data-efx-height | 260 | Chart height in px (0 = element CSS height). |
data-efx-colors | Shine tones | Series colors "#f43f5e|#8b5cf6". |
data-efx-prefix / suffix | Value formatting, e.g. "$" or "%". | |
data-efx-compact | false | 12.3k style numbers. |
data-efx-decimals | -1 | Fixed decimals (-1 = auto). |
data-efx-legend / tooltip / animate | true | Turn parts off. |
data-efx-background | false | Decorative: fills the element behind its content (no axes/tooltip). |
data-efx-title | Accessible name (else aria-label or first heading). |
| CSS variable | Default | Controls |
|---|---|---|
--efx-chart-1 … 7 | Shine tones | Palette. |
--efx-chart-grid | border color | Gridlines. |
--efx-chart-text | muted text | Axis labels. |
--efx-chart-bg-opacity | .35 | Opacity in background mode. |
| Event | When |
|---|---|
efx:select | Bar clicked / Enter pressed. detail = { index, label, value, series }. |
efx:data (listen) | Dispatch on the chart with detail { labels, series } to update it. |
chart-box
2.4 KBBox-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.
A box plot as a card background.
{"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.| Class | What it does |
|---|---|
efx-chart-box | Renders a box plot from JSON samples or summaries. |
| Attribute | Default | Values |
|---|---|---|
data-efx-data | JSON: {labels, series:[{name, data:[[samples]…]}]} or [{label,min,q1,median,q3,max,outliers}]. | |
data-efx-labels | Category labels: "A|B|C". | |
data-efx-names | Series names for the legend. | |
data-efx-horizontal | false | Horizontal boxes. |
data-efx-grid | true | Gridlines. |
data-efx-height | 260 | Chart height in px (0 = element CSS height). |
data-efx-colors | Shine tones | Colors "#f43f5e|#8b5cf6". |
data-efx-prefix / suffix | Value formatting, e.g. "$" or "%". | |
data-efx-compact / decimals / format | false / -1 | Number formatting (or a registered formatter name). |
data-efx-tooltip / animate | true | Turn parts off. |
data-efx-background | false | Decorative: fills the element behind its content (no axes/tooltip). |
data-efx-title | Accessible name (else aria-label or first heading). |
| CSS variable | Default | Controls |
|---|---|---|
--efx-chart-1 … 7 | Shine tones | Palette. |
--efx-chart-grid / text | theme | Gridlines and axis labels. |
--efx-chart-bg-opacity | .35 | Opacity in background mode. |
| Event | When |
|---|---|
efx:select | Box 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. |
chart-bullet
2.3 KBStephen Few bullet chart: grayscale qualitative bands, a colored measure bar and a target tick per row. Compact enough for KPI cards; horizontal by default.
[{"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).| Class | What it does |
|---|---|
efx-chart-bullet | Renders bullet rows from JSON rows or flat values + targets + ranges. |
| Attribute | Default | Values |
|---|---|---|
data-efx-data | JSON rows [{label, value, target, ranges:[…], max?}] or "270,45" with labels/targets/ranges. | |
data-efx-labels | Row labels (flat form): "Revenue|Profit". | |
data-efx-targets | Targets (flat form): "300|50" (one value = all rows). | |
data-efx-ranges | Band upper bounds for every row: "150,225,300". | |
data-efx-vertical | false | Columns instead of rows. |
data-efx-bar-height | 18 | Thickness of each bullet in px (try 10 for a compact list). |
data-efx-shared | false | One common scale and axis for all rows. |
data-efx-values | true | Print the value next to each row. |
data-efx-height | 220 | Height in px (vertical only; rows size themselves). |
data-efx-colors | Shine tones | Measure bar color. |
data-efx-prefix / suffix | Value formatting. | |
data-efx-compact / decimals / format | false / -1 | Number formatting (or a registered formatter name). |
data-efx-tooltip / animate | true | Turn parts off. |
data-efx-background | false | Decorative: bands and bars fill the element behind its content. |
data-efx-title | Accessible name. |
| CSS variable | Default | Controls |
|---|---|---|
--efx-chart-1 | Shine primary | Measure bar. |
--efx-chart-text | muted text | Row labels. |
--efx-chart-bg-opacity | .35 | Opacity in background mode. |
| Event | When |
|---|---|
efx:select | Row 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. |
chart-candle
2.2 KBCandlestick 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.
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.| Class | What it does |
|---|---|
efx-chart-candle | Renders OHLC data as candles or OHLC bars. |
| Attribute | Default | Values |
|---|---|---|
data-efx-data | JSON [{label,o,h,l,c,v?}] or OHLC(V) series arrays. | |
data-efx-labels | Period labels (series form): "Mon|Tue|Wed". | |
data-efx-style | candle | <code>candle</code> (body + wick) or <code>ohlc</code> (open/close ticks). |
data-efx-volume | false | Volume bars in the bottom 20% of the plot. |
data-efx-colors | success / danger | Override as "up|down". |
data-efx-prefix / suffix | Value formatting, e.g. "$". | |
data-efx-compact / decimals / format | Number formatting. | |
data-efx-height | 260 | Chart height in px. |
data-efx-tooltip / animate / grid | true | Turn parts off. |
data-efx-background | false | Decorative: fills the element behind its content. |
data-efx-title | Accessible name. |
| CSS variable | Default | Controls |
|---|---|---|
--sh-success / --sh-danger | Shine tones | Up and down colors. |
--efx-chart-grid / --efx-chart-text | Gridlines and axis text. |
| Event | When |
|---|---|
efx:select | Candle clicked / Enter pressed. detail = { index, label, value (close) }. |
efx:data (listen) | Dispatch with detail as the rows array, {rows:[…]}, or { labels, series }. |
chart-combo
2.4 KBBars 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.
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.| Class | What it does |
|---|---|
efx-chart-combo | Renders bars and lines from data-efx-data (per-series type and axis) or inline JSON. |
| Attribute | Default | Values |
|---|---|---|
data-efx-data | JSON [{"name","data","type":"bar|line","axis":"left|right"}] or "40,52|22,31". | |
data-efx-labels | Category labels: "Jan|Feb|Mar". | |
data-efx-names | Series names: "Revenue|Margin %". | |
data-efx-types | Per-series fallback: "bar|line" (first series bar, others line when omitted). | |
data-efx-axes | Per-series fallback: "left|right". | |
data-efx-smooth | true | Smooth (monotone) lines. |
data-efx-dots | true | Dots on line points (false = only on hover). |
data-efx-area | false | Gradient fill under the lines. |
data-efx-radius | 4 | Bar corner radius. |
data-efx-prefix / suffix | Left axis and tooltip value formatting, e.g. "$" / "k". | |
data-efx-prefix2 / suffix2 | Right axis formatting, e.g. "%". | |
data-efx-height | 260 | Chart height in px. |
data-efx-colors | Shine tones | Series colors "#f43f5e|#8b5cf6". |
data-efx-legend / tooltip / animate / grid | true | Turn parts off. |
data-efx-background | false | Decorative: fills the element behind its content. |
data-efx-title | Accessible name. |
| CSS variable | Default | Controls |
|---|---|---|
--efx-chart-1 … 7 | Shine tones | Palette. |
| Event | When |
|---|---|
efx:select | Column clicked / Enter pressed. detail = { index, label, value, series }. |
efx:data (listen) | Dispatch with detail { labels, series:[{name, values, type, axis}] } to update. |
chart-flow
2.5 KBLightweight 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.
A flow as a card background.
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.| Class | What it does |
|---|---|
efx-chart-flow | Renders a flow diagram from { nodes, links } JSON. |
| Attribute | Default | Values |
|---|---|---|
data-efx-data | JSON {"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-width | 12 | Node bar width in px. |
data-efx-node-pad | 12 | Vertical gap between nodes in a column. |
data-efx-align | justify | "justify" pushes end nodes to the last column, "left" keeps them where they are. |
data-efx-colors | Shine tones | Node colors (ribbons take their source node color). |
data-efx-height | 260 | Chart height in px. |
data-efx-prefix / suffix / compact / decimals | Value formatting. | |
data-efx-tooltip / animate | true | Turn parts off. |
data-efx-background | false | Decorative: fills the element behind its content (no labels). |
data-efx-title | Accessible name. |
| CSS variable | Default | Controls |
|---|---|---|
--efx-chart-1 … 7 | Shine tones | Palette. |
--efx-chart-bg-opacity | .35 | Opacity in background mode. |
| Event | When |
|---|---|
efx:select | Link or node clicked / Enter pressed. detail = { index, label, value }. |
efx:data (listen) | Dispatch with detail { nodes, links } to update. |
chart-funnel
3.7 KBConversion 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.
Decorative mode fills the whole card.
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":[…]}].| Class | What it does |
|---|---|
efx-chart-funnel | Renders a funnel from data-efx-data (first series) and data-efx-labels (stage names). |
| Attribute | Default | Values |
|---|---|---|
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-labels | Stage names: "Visits|Signups|Trials|Paid". | |
data-efx-style | curved | <code>curved</code> smooth trapezoid stack · <code>straight</code> · <code>bars</code> centered bars with drop-off connectors · <code>pyramid</code>. |
data-efx-horizontal | false | Flow left to right. |
data-efx-neck | 0.25 | Bottom width ratio for curved/straight. 0 = widths proportional to each value. |
data-efx-gap | 4 | Pixels between stages. |
data-efx-conversion | true | Show % of first stage and the "−32%" drop-off between stages. |
data-efx-show | inside | Stage 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-dynamic | true | Stage height proportional to value (false = equal heights). |
data-efx-compare | mirror | With 2+ series: <code>mirror</code> halves side by side · <code>ghost</code> series 2 as an outline behind series 1. |
data-efx-height | 320 | Chart height in px (0 = element CSS height). |
data-efx-colors | Shine tones | Colors "#f43f5e|#8b5cf6" (per stage / slice / series). |
data-efx-prefix / suffix | Value formatting, e.g. "$" or "%". | |
data-efx-compact | false | 12.3k style numbers. |
data-efx-decimals | -1 | Fixed decimals (-1 = auto). |
data-efx-tooltip / animate | true | Turn parts off. |
data-efx-background | false | Decorative: fills the element behind its content (no labels/tooltip). |
data-efx-title | Accessible name (else aria-label or first heading). |
| CSS variable | Default | Controls |
|---|---|---|
--efx-chart-1 … 7 | Shine tones | Palette. |
--efx-chart-text | muted text | Secondary labels and drop-off rates. |
| Event | When |
|---|---|
efx:select | Stage clicked / Enter pressed. detail = { index, label, value, series }. |
efx:data (listen) | Dispatch on the chart with detail { labels, series } to update it. |
chart-gauge
2.3 KBA 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.
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 }.| Class | What it does |
|---|---|
efx-chart-gauge | Renders a gauge from data-efx-value (or the first data value). |
| Attribute | Default | Values |
|---|---|---|
data-efx-type | gauge | <code>gauge</code> 240° arc · <code>ring</code> full circle · <code>radial</code> one concentric ring per label. |
data-efx-value | first data value | Current value. |
data-efx-min / max | 0 / 100 | Scale. |
data-efx-thick | 0.18 | Arc thickness as a ratio of the radius. |
data-efx-needle | false | Show a needle (gauge only). |
data-efx-target | Draw a target tick at this value. | |
data-efx-label | Caption under the value. | |
data-efx-data / labels | For radial: "80,60,35" and "Move|Exercise|Stand". | |
data-efx-height | 320 | Chart height in px (0 = element CSS height). |
data-efx-colors | Shine tones | Colors "#f43f5e|#8b5cf6" (per stage / slice / series). |
data-efx-prefix / suffix | Value formatting, e.g. "$" or "%". | |
data-efx-compact | false | 12.3k style numbers. |
data-efx-decimals | -1 | Fixed decimals (-1 = auto). |
data-efx-tooltip / animate | true | Turn parts off. |
data-efx-background | false | Decorative: fills the element behind its content (no labels/tooltip). |
data-efx-title | Accessible name (else aria-label or first heading). |
| CSS variable | Default | Controls |
|---|---|---|
--efx-chart-1 … 7 | Shine tones | Arc colors (first = gauge/ring). |
| Event | When |
|---|---|
efx:select | Arc clicked. detail = { index, label, value }. |
efx:data (listen) | Dispatch with detail { labels, series } to update. |
chart-heatmap
2.3 KBA 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.
Diverging scale behind a card
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).| Class | What it does |
|---|---|
efx-chart-heatmap | Renders a heatmap from data-efx-data, inline JSON or a table. |
| Attribute | Default | Values |
|---|---|---|
data-efx-data | Grid: "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 / names | Grid column labels "Mon|Tue" / row names "Morning|Evening". | |
data-efx-source | CSS selector of a Shine table to read (first column = labels). | |
data-efx-calendar | false | Calendar 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-gap | 2 | Space between cells in px. |
data-efx-radius | 2 | Cell corner radius. |
data-efx-height | auto | px. Default: 30px per row (grid) or square cells (calendar, max 20px). |
data-efx-colors | Shine tones | Ramp color, or "#positive|#negative" for diverging. |
data-efx-prefix / suffix / compact / decimals | Tooltip value formatting. | |
data-efx-tooltip / animate | true | Turn parts off. |
data-efx-background | false | Decorative: cells stretch edge to edge behind the element content. |
data-efx-title | Accessible name (else aria-label or first heading). |
| CSS variable | Default | Controls |
|---|---|---|
--efx-chart-1 … 7 | Shine tones | Palette. |
--efx-chart-text | muted | Axis text and empty cells. |
| Event | When |
|---|---|
efx:select | Cell clicked / Enter pressed. detail = { index, label, value, series }. |
efx:data (listen) | Grid: detail { labels, series }. Calendar: detail [{date,value}]. |
chart-histogram
1.7 KBAuto-binned histogram of raw values with touching bars and an optional normal-curve overlay. Tooltip shows the bin range and count.
A histogram as a card background.
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:[…]}]}.| Class | What it does |
|---|---|
efx-chart-histogram | Bins the values and renders a histogram. |
| Attribute | Default | Values |
|---|---|---|
data-efx-data | "1.2,3.4,2.2,…" or JSON [1.2,3.4,…]. | |
data-efx-bins | 0 | Exact number of bins (0 = Sturges). |
data-efx-step | 0 | Fixed bin width (wins over bins). |
data-efx-curve | false | Overlay a fitted normal curve. |
data-efx-grid | true | Gridlines. |
data-efx-height | 260 | Chart height in px (0 = element CSS height). |
data-efx-colors | Shine tones | Colors "#f43f5e|#8b5cf6". |
data-efx-prefix / suffix | Value formatting, e.g. "$" or "%". | |
data-efx-compact / decimals / format | false / -1 | Number formatting (or a registered formatter name). |
data-efx-tooltip / animate | true | Turn parts off. |
data-efx-background | false | Decorative: fills the element behind its content (no axes/tooltip). |
data-efx-title | Accessible name (else aria-label or first heading). |
| CSS variable | Default | Controls |
|---|---|---|
--efx-chart-1 … 2 | Shine tones | Bars (1) and curve (2). |
--efx-chart-grid / text | theme | Gridlines and axis labels. |
--efx-chart-bg-opacity | .35 | Opacity in background mode. |
| Event | When |
|---|---|
efx:select | Bin clicked / Enter pressed. detail = { index, label: "[a, b)", value: count }. |
efx:data (listen) | Dispatch with detail { series:[{values}] } to update. |
chart-line
2.3 KBMulti-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.
$34k this week
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).| Class | What it does |
|---|---|
efx-chart-line | Renders a line / area chart from data-efx-data, inline JSON or a table. |
| Attribute | Default | Values |
|---|---|---|
data-efx-data | "3,5,4" · several series "3,5|4,1" · JSON [[3,5],[4,1]] or [{"name":"A","data":[…]}] | |
data-efx-labels | X labels: "Mon|Tue|Wed". | |
data-efx-names | Series names: "2025|2026". | |
data-efx-source | CSS selector of a Shine table to read (first column = labels). | |
data-efx-area | false | Gradient fill under each line (35% → 0 of the series color). |
data-efx-stacked | false | Stacked area (implies area). |
data-efx-stream | false | Streamgraph: stacked areas around a centred wiggle baseline (no y axis), smooth. Tooltip still shows real values. |
data-efx-smooth | true | Monotone curve; false = straight segments. |
data-efx-dots | true | Always-visible dots; false shows them only under the crosshair. |
data-efx-grid | true | Horizontal gridlines. |
data-efx-min | (auto) | Y axis minimum; empty = automatic. |
data-efx-height | 260 | Chart height in px (0 = element CSS height). |
data-efx-colors | Shine tones | Series colors "#f43f5e|#8b5cf6". |
data-efx-prefix / suffix | Value formatting, e.g. "$" or "%". | |
data-efx-compact / decimals | false / -1 | 12.3k style numbers / fixed decimals. |
data-efx-legend / tooltip / animate | true | Turn parts off. |
data-efx-background | false | Decorative: fills the element behind its content (lines/areas only). |
data-efx-title | Accessible name (else aria-label or first heading). |
| CSS variable | Default | Controls |
|---|---|---|
--efx-chart-1 … 7 | Shine tones | Palette. |
--efx-chart-grid / --efx-chart-text | border / muted | Gridlines and axis text. |
| Event | When |
|---|---|
efx:select | Point clicked / Enter pressed. detail = { index, label, value, series }. |
efx:data (listen) | Dispatch on the chart with detail { labels, series } to update it. |
chart-pie
2.6 KBPie, 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.
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).| Class | What it does |
|---|---|
efx-chart-pie | Renders a pie/donut from data-efx-data (first series) and data-efx-labels. |
| Attribute | Default | Values |
|---|---|---|
data-efx-data | "40,30,20,10" · JSON · or a table via data-efx-source. | |
data-efx-labels | Slice names: "A|B|C|D". | |
data-efx-donut | 0.6 | Inner radius ratio (0 = full pie). |
data-efx-pad | 0.01 | Gap between slices in radians. |
data-efx-sort | false | Largest slice first. |
data-efx-center | Text in the donut hole. <code>{total}</code> = formatted total. Empty shows the total with caption "Total". | |
data-efx-show | auto | Labels: <code>auto</code> outside with leader lines when there is room · <code>percent</code> inside slices · <code>none</code>. |
data-efx-half | false | Semicircle. |
data-efx-rose | false | Polar-area (Nightingale) rose: equal angles, radius proportional to √value. |
data-efx-legend | true | Legend keys toggle slices. |
data-efx-height | 320 | Chart height in px (0 = element CSS height). |
data-efx-colors | Shine tones | Colors "#f43f5e|#8b5cf6" (per stage / slice / series). |
data-efx-prefix / suffix | Value formatting, e.g. "$" or "%". | |
data-efx-compact | false | 12.3k style numbers. |
data-efx-decimals | -1 | Fixed decimals (-1 = auto). |
data-efx-tooltip / animate | true | Turn parts off. |
data-efx-background | false | Decorative: fills the element behind its content (no labels/tooltip). |
data-efx-title | Accessible name (else aria-label or first heading). |
| CSS variable | Default | Controls |
|---|---|---|
--efx-chart-1 … 7 | Shine tones | Palette. |
| Event | When |
|---|---|
efx:select | Slice clicked / Enter pressed. detail = { index, label, value }. |
efx:data (listen) | Dispatch on the chart with detail { labels, series } to update it. |
chart-progress
1.6 KBCompact 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.
Progress bars as a card background.
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.| Class | What it does |
|---|---|
efx-chart-progress | Renders one progress bar per label. |
| Attribute | Default | Values |
|---|---|---|
data-efx-data | Values "820,64,45" or two series "820,64|1000,80" (second series = targets). JSON works too. | |
data-efx-labels | Row labels: "Signups|Revenue|NPS". | |
data-efx-source | CSS selector of a Shine table (column 1 = labels, 2 = values, 3 = targets). | |
data-efx-max | auto | Common scale for every row. Auto: each row with a target scales to max(target, value); otherwise the largest value. |
data-efx-values | true | Show "value / target" on the right. |
data-efx-percent | true | Show the percentage (value / target, else value / scale). |
data-efx-thick | 10 | Bar thickness in px. |
data-efx-radius | 999 | Bar corner radius (999 = pill). |
data-efx-colors | Shine tones | Cycled per row; give one color to use it everywhere. |
data-efx-height | auto | Defaults to a height that fits all rows. |
data-efx-prefix / suffix / compact / decimals | Value formatting. | |
data-efx-tooltip / animate | true | Turn parts off. |
data-efx-background | false | Decorative: bars fill the element behind its content. |
data-efx-title | Accessible name. |
| CSS variable | Default | Controls |
|---|---|---|
--efx-chart-1 … 7 | Shine tones | Palette. |
--sh-surface-2 | Shine | Track color. |
| Event | When |
|---|---|
efx:select | Row clicked / Enter pressed. detail = { index, label, value }. |
efx:data (listen) | Dispatch with detail { labels, series } to update. |
chart-radar
2.0 KBRadar / spider chart: one polygon per series, one axis per label. Hover vertices for values, click a legend key to hide a series.
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.| Class | What it does |
|---|---|
efx-chart-radar | Renders a radar chart (needs 3+ labels). |
| Attribute | Default | Values |
|---|---|---|
data-efx-data | "8,6,7,5,9" · several series "8,6,7,5,9|5,8,4,7,6" · JSON. | |
data-efx-labels | Axis names: "Speed|Power|Range|Cost|Style". | |
data-efx-names | Series names: "A|B". | |
data-efx-levels | 4 | Number of grid rings. |
data-efx-area | true | Fill the polygons. |
data-efx-dots | true | Show vertex dots (hover still works when off). |
data-efx-max | auto | Value at the outer ring. |
data-efx-height | 320 | Chart height in px (0 = element CSS height). |
data-efx-colors | Shine tones | Colors "#f43f5e|#8b5cf6" (per stage / slice / series). |
data-efx-prefix / suffix | Value formatting, e.g. "$" or "%". | |
data-efx-compact | false | 12.3k style numbers. |
data-efx-decimals | -1 | Fixed decimals (-1 = auto). |
data-efx-tooltip / animate | true | Turn parts off. |
data-efx-background | false | Decorative: fills the element behind its content (no labels/tooltip). |
data-efx-title | Accessible name (else aria-label or first heading). |
| CSS variable | Default | Controls |
|---|---|---|
--efx-chart-1 … 7 | Shine tones | Series colors. |
--efx-chart-grid | border color | Rings and axes. |
| Event | When |
|---|---|
efx:select | Vertex clicked / Enter pressed. detail = { index, label, value, series }. |
efx:data (listen) | Dispatch with detail { labels, series } to update. |
chart-scatter
2.2 KBScatter 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.
Clusters by size
{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.| Class | What it does |
|---|---|
efx-chart-scatter | Renders a scatter / bubble chart from data-efx-data or inline JSON points. |
| Attribute | Default | Values |
|---|---|---|
data-efx-data | JSON points [{"x":1,"y":4,"r":3,"label":"A"}] · several series [[{…}],[{…}]] or [{"name":"A","points":[…]}]. | |
data-efx-names | Series names: "2025|2026". | |
data-efx-x-label / y-label | Axis titles (also used in the tooltip). | |
data-efx-connected | false | Join each series' points in data order with a line and an arrow at the end (trajectories, paths over time). |
data-efx-bubble | false | Size points by r (radius scales with the square root, up to 24px). |
data-efx-height | 260 | Chart height in px (0 = element CSS height). |
data-efx-colors | Shine tones | Series colors "#f43f5e|#8b5cf6". |
data-efx-prefix / suffix / compact / decimals | Formatting for y values and y ticks. | |
data-efx-legend / tooltip / animate | true | Turn parts off. |
data-efx-background | false | Decorative: fills the element behind its content. |
data-efx-title | Accessible name (else aria-label or first heading). |
| CSS variable | Default | Controls |
|---|---|---|
--efx-chart-1 … 7 | Shine tones | Palette. |
--efx-chart-grid / --efx-chart-text | border / muted | Gridlines and axis text. |
| Event | When |
|---|---|
efx:select | Point clicked / Enter pressed. detail = { index, label, value (y), series }. |
efx:data (listen) | Dispatch with detail { series: [{ name, points: [{x,y,r?,label?}] }] } to update. |
chart-spark
1.9 KBA 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.
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.| Class | What it does |
|---|---|
efx-chart-spark | Renders a sparkline (line, bar or win-loss) from data-efx-data. |
| Attribute | Default | Values |
|---|---|---|
data-efx-data | "3,5,4,8" (first series only) · JSON [3,5,4]. | |
data-efx-labels | Tooltip labels: "Mon|Tue|Wed" (default 1, 2, 3…). | |
data-efx-type | line | line · bar · win-loss (positive values up, negative down). |
data-efx-area | true | Gradient fill under the line (type line). |
data-efx-last | true | Dot on the last point (type line). |
data-efx-smooth | true | Monotone curve (type line). |
data-efx-height | 40 / 1.2em | Height in px; inline elements default to 1.2em, others to 40. |
data-efx-colors | Shine tones | Line/bar color; win-loss uses "#win|#loss" (default success / danger). |
data-efx-prefix / suffix / compact / decimals | Tooltip value formatting. | |
data-efx-legend | false | Legend (off by default). |
data-efx-tooltip / animate | true | Turn parts off. |
data-efx-background | false | Decorative: fills the element behind its content. |
data-efx-title | Accessible name (else aria-label or first heading). |
| CSS variable | Default | Controls |
|---|---|---|
--efx-chart-1 … 7 | Shine tones | Palette. |
--efx-chart-bg-opacity | .35 | Opacity in background mode. |
| Event | When |
|---|---|
efx:select | Point clicked / Enter pressed. detail = { index, label, value }. |
efx:data (listen) | Dispatch with detail { series: [{ values }] } to update. |
chart-sunburst
2.8 KBRadial 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.
Disk usage
A sunburst as a card background.
{"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.| Class | What it does |
|---|---|
efx-chart-sunburst | Renders a sunburst from a JSON tree. |
| Attribute | Default | Values |
|---|---|---|
data-efx-data | JSON tree {name, value?, children:[…]}. | |
data-efx-depth | 4 | Rings shown at once (zooming reveals deeper levels). |
data-efx-captions | true | Print names on arcs that are big enough. |
data-efx-height | 320 | Chart height in px. |
data-efx-colors | Shine tones | One color per top-level branch. |
data-efx-prefix / suffix | Value formatting. | |
data-efx-compact / decimals / format | false / -1 | Number formatting (or a registered formatter name). |
data-efx-tooltip / animate | true | Turn parts off. |
data-efx-background | false | Decorative: a quiet sunburst behind the element's content. |
data-efx-title | Accessible name. |
| CSS variable | Default | Controls |
|---|---|---|
--efx-chart-1 … 7 | Shine tones | Branch colors. |
--efx-chart-bg-opacity | .35 | Opacity in background mode. |
| Event | When |
|---|---|
efx:select | Arc 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. |
chart-timeline
2.8 KBGantt-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.
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.| Class | What it does |
|---|---|
efx-chart-timeline | Renders rows of {label, start, end} as a Gantt chart. |
| Attribute | Default | Values |
|---|---|---|
data-efx-data | JSON [{label, start, end, group?, color?, progress?}] (dates or numbers). | |
data-efx-today | true | Marker for the current date when it falls inside the range (dates only). |
data-efx-radius | 4 | Bar corner radius. |
data-efx-colors | Shine tones | Group colors "#f43f5e|#8b5cf6" (a row's own color wins). |
data-efx-prefix / suffix / format | Formatting for numeric axes and durations. | |
data-efx-tooltip / animate / grid | true | Turn parts off. |
data-efx-background | false | Decorative: bars only, filling the element behind its content. |
data-efx-title | Accessible name. |
| CSS variable | Default | Controls |
|---|---|---|
--efx-chart-1 … 7 | Shine tones | Group palette (Today marker uses the 6th). |
| Event | When |
|---|---|
efx:select | Row clicked / Enter pressed. detail = { index, label, value (duration) }. |
efx:data (listen) | Dispatch with detail as the rows array or {rows:[…]} to update. |
chart-treemap
2.0 KBSquarified 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.
A treemap as a card background.
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.| Class | What it does |
|---|---|
efx-chart-treemap | Renders a treemap from labels and the first data series. |
| Attribute | Default | Values |
|---|---|---|
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-labels | Tile labels: "Rent|Food|Travel". | |
data-efx-source | CSS selector of a Shine table to read. | |
data-efx-gap | 2 | Gap between tiles in px. |
data-efx-radius | 4 | Tile corner radius. |
data-efx-captions | true | Print label and value inside tiles that are big enough. |
data-efx-sort | true | Largest tile first (false keeps data order). |
data-efx-colors | Shine tones | Cycled per tile; a single color gives a ramp by rank. |
data-efx-height | 260 | Chart height in px (0 = element CSS height). |
data-efx-prefix / suffix | Value formatting, e.g. "$". | |
data-efx-compact / decimals | false / -1 | Number formatting. |
data-efx-tooltip / animate | true | Turn parts off. |
data-efx-background | false | Decorative: fills the element behind its content. |
data-efx-title | Accessible name. |
| CSS variable | Default | Controls |
|---|---|---|
--efx-chart-1 … 7 | Shine tones | Palette. |
--efx-chart-bg-opacity | .35 | Opacity in background mode. |
| Event | When |
|---|---|
efx:select | Tile clicked / Enter pressed. detail = { index, label, value }. |
efx:data (listen) | Dispatch with detail { labels, series } to update. |
chart-waterfall
1.7 KBRunning-total bars: green for increases, red for decreases, primary for totals, joined by connector lines. Tooltip shows the change and the 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).| Class | What it does |
|---|---|
efx-chart-waterfall | Renders a waterfall from deltas in data-efx-data and total indexes in data-efx-totals. |
| Attribute | Default | Values |
|---|---|---|
data-efx-data | Deltas: "100,30,-20,15" · JSON [{"label","value"}] · table via data-efx-source. | |
data-efx-labels | Step names: "Start|Sales|Costs|End". | |
data-efx-totals | Indexes drawn as total bars, e.g. "0|5" (negative counts from the end). | |
data-efx-values | true | Print the value above each bar (+30, −20 …). |
data-efx-connectors | true | Dashed lines linking one bar to the next. |
data-efx-radius | 3 | Bar corner radius. |
data-efx-colors | success / danger / primary | Override as "total|up|down". |
data-efx-prefix / suffix | Value formatting, e.g. "$" or "k". | |
data-efx-compact / decimals / format | Number formatting (format = registered formatter). | |
data-efx-height | 260 | Chart height in px. |
data-efx-tooltip / animate / grid | true | Turn parts off. |
data-efx-background | false | Decorative: fills the element behind its content. |
data-efx-title | Accessible name. |
| CSS variable | Default | Controls |
|---|---|---|
--sh-success / --sh-danger / --sh-primary | Shine tones | Up, down and total colors. |
--efx-chart-grid / --efx-chart-text | Gridlines and axis text. |
| Event | When |
|---|---|
efx:select | Bar clicked / Enter pressed. detail = { index, label, value }. |
efx:data (listen) | Dispatch with detail { labels, series:[{values}] } to update. |
diagram-cycle
2.3 KBNumbered 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.
Cycle as a card background.
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.| Class | What it does |
|---|---|
efx-diagram-cycle | Renders a loop diagram from data-efx-labels. |
| Attribute | Default | Values |
|---|---|---|
data-efx-labels | Step names in order: "Plan|Build|Measure|Learn". | |
data-efx-descriptions | Tooltip text per step, "a|b|c". | |
data-efx-center | Label in the middle; "|" starts a new line. | |
data-efx-numbers | true | Number the steps. |
data-efx-flow | true | Animate dashes flowing along the arrows. |
data-efx-start | 0 | Angle of step 1 in degrees (0 = top, clockwise). |
data-efx-height | 340 | Chart height in px (0 = element CSS height). |
data-efx-colors | Shine tones | One color per step. |
data-efx-tooltip / animate | true | Turn parts off. |
data-efx-background | false | Decorative: just nodes and arrows, behind the content. |
data-efx-title | Accessible name (else aria-label or first heading). |
| CSS variable | Default | Controls |
|---|---|---|
--efx-chart-1 … 7 | Shine tones | Step colors. |
--efx-chart-text | muted text | Arrows. |
--efx-chart-bg-opacity | .35 | Opacity in background mode. |
| Event | When |
|---|---|
efx:select | Step clicked / Enter pressed. detail = { index, label, value }. |
efx:data (listen) | Dispatch on the diagram with detail { labels, descriptions } to update it. |
diagram-fishbone
2.7 KBIshikawa 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.
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.| Class | What it does |
|---|---|
efx-diagram-fishbone | Renders the diagram from JSON or a nested list. |
| Attribute | Default | Values |
|---|---|---|
data-efx-problem | Problem (head of the fish). Overrides the JSON value. | |
data-efx-data | JSON {problem, causes:[{name, items[]}]}. | |
data-efx-colors | Shine tones | Bone colors. |
data-efx-title | Accessible name. |
| CSS variable | Default | Controls |
|---|---|---|
--efx-chart-1 … 7 | Shine tones | Bone palette. |
| Event | When |
|---|---|
efx:select | Bone clicked / Enter pressed. detail = { index, label, items, problem }. |
efx:data (listen) | Dispatch with detail { problem, causes } to update. |
diagram-flow
6.7 KBOne 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.
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).| Class | What it does |
|---|---|
efx-diagram-flow | The 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. |
| Attribute | Default | Values |
|---|---|---|
data-efx-edges | Connections: "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-direction | TB | Auto layout direction: TB (top to bottom) or LR. |
data-efx-cols | 0 | Grid columns when using data-efx-cell (inferred from the cells if 0). Also valid on a group. |
data-efx-lanes | Swimlane 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-route | orth | "orth" elbow connectors, "curve" or "straight". |
data-efx-flow | false | Animated dots travelling along each connector (off for reduced motion). |
data-efx-colors | Shine tones | Palette for numeric tones (data-efx-tone="3"). |
data-efx-title | Accessible name. |
| CSS variable | Default | Controls |
|---|---|---|
--efx-diagram-gap | 3rem 3.5rem | Gap between nodes. |
--efx-lane-h | 5.5rem | Minimum swimlane height. |
--efx-edge | text-muted | Default connector color (a node tone colors its outgoing edges). |
--efx-n | per tone | Node accent color; set it on a node to override. |
| Event | When |
|---|---|
efx:select | Node clicked / Enter or Space pressed. detail = { id, label, index }. |
chart-pyramid
2.1 KBLayered 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.
Pyramid as a card background.
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.| Class | What it does |
|---|---|
efx-chart-pyramid | Renders a pyramid from data-efx-labels (and optional values). |
| Attribute | Default | Values |
|---|---|---|
data-efx-labels | Tier names top → bottom: "A|B|C". | |
data-efx-data | Optional values "1,3,6,12": tier heights follow them. | |
data-efx-equal | false | Equal tier heights even when values exist. |
data-efx-inverted | false | Point the triangle down (widest tier on top). |
data-efx-notes | Side annotations, one per tier "Why|Where|How". | |
data-efx-gap | 3 | Gap between tiers in px. |
data-efx-height | 320 | Chart height in px (0 = element CSS height). |
data-efx-colors | Shine tones | One color per tier. |
data-efx-legend / tooltip / animate | true | Turn parts off. |
data-efx-background | false | Decorative: just the tiers, behind the content. |
data-efx-title | Accessible name (else aria-label or first heading). |
| CSS variable | Default | Controls |
|---|---|---|
--efx-chart-1 … 7 | Shine tones | Tier colors. |
--efx-chart-text | muted text | Side notes. |
--efx-chart-bg-opacity | .35 | Opacity in background mode. |
| Event | When |
|---|---|
efx:select | Tier clicked / Enter pressed. detail = { index, label, value }. |
efx:data (listen) | Dispatch on the chart with detail { labels, series } to update it. |
chart-quadrant
2.7 KBPrioritisation 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.
The matrix sits behind this card as a background.
[{"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:[…]}).| Class | What it does |
|---|---|
efx-chart-quadrant | Renders a 2×2 matrix from a list of {label, x, y} items. |
| Attribute | Default | Values |
|---|---|---|
data-efx-data | JSON items [{"label","x","y","r?","group?"}]. | |
data-efx-quadrants | Names "Quick wins|Big bets|Fill-ins|Money pits" (top-left, top-right, bottom-left, bottom-right). | |
data-efx-x-label / y-label | Axis titles, e.g. "Effort →". | |
data-efx-x-domain / y-domain | 0,100 | Value range of each axis, e.g. "0,10". |
data-efx-height | 360 | Chart height in px (0 = element CSS height). |
data-efx-colors | Shine tones | Palette; groups and quadrant tints use it in order. |
data-efx-tooltip / animate | true | Turn parts off. |
data-efx-background | false | Decorative: tinted quadrants and dots only, behind the content. |
data-efx-title | Accessible name (else aria-label or first heading). |
| CSS variable | Default | Controls |
|---|---|---|
--efx-chart-1 … 7 | Shine tones | Palette. |
--efx-chart-text | muted text | Axis titles and quadrant names. |
--efx-chart-bg-opacity | .35 | Opacity in background mode. |
| Event | When |
|---|---|
efx:select | Dot clicked / Enter pressed. detail = { index, label, value, series }. |
efx:data (listen) | Dispatch on the chart with detail = an items array to update it. |
diagram-sequence
6.6 KBDraws 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.
<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).| Class | What it does |
|---|---|
efx-diagram-sequence | Container; the text lives in an inline script (or data-efx-data). |
| Attribute | Default | Values |
|---|---|---|
data-efx-data | The diagram text or JSON (otherwise read from the inline <script type="text/plain"> / <pre>). | |
data-efx-play | false | Draw messages in one by one when scrolled into view (static for reduced motion). |
data-efx-step | 420 | Play: ms between messages. |
data-efx-activations | false | Automatic activation bars: a sync/async message activates its target until it returns. |
data-efx-numbers | false | Number the messages (or write <code>autonumber</code>). |
data-efx-bottom | false | Repeat participant boxes at the bottom. |
data-efx-gap | 0 | Minimum px between lifelines (0 = auto). |
data-efx-colors | Shine tones | Participant accent colors. |
data-efx-tooltip | true | Keyboard-step tooltip. |
data-efx-title | Accessible name. |
| CSS variable | Default | Controls |
|---|---|---|
--efx-seq-line | muted text | Arrow color. |
--efx-seq-note | tinted warning | Note fill. |
| Event | When |
|---|---|
efx:select | Message clicked. detail = { index, label, from, to }. |
efx:data (listen) | Dispatch with detail = new text or JSON to redraw. |
diagram-tree
4.9 KBTurns 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.
<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.| Class | What it does |
|---|---|
efx-diagram-tree | On a <ul>: lay the list out as a diagram. |
| Attribute | Default | Values |
|---|---|---|
data-efx-direction | down | "down" (org chart) or "right" (horizontal tree). |
data-efx-layout | tree | "mindmap" centres the root and splits its children left/right. |
data-efx-links | elbow | "elbow", "curve" or "straight" connectors. |
data-efx-collapsible | true | Branches fold on click / Enter / Space. |
data-efx-collapse | 0 | Start folded from this depth (1 = fold every branch below the root's children). 0 = all open. |
data-efx-gap | 16 | Gap between siblings in px. |
data-efx-level-gap | 44 | Gap between levels in px. |
data-efx-tone | Default tone for every node (a Shine tone name). | |
data-efx-animate | true | Entrance + fold animation (off for reduced motion). |
data-efx-title | Accessible name (or aria-label on the list). |
| CSS variable | Default | Controls |
|---|---|---|
--efx-tree-line | muted | Connector colour. |
--efx-tone | per node | Node accent + connector colour; set by data-efx-tone. |
| Event | When |
|---|---|
efx:select | Node clicked / Enter. detail = { label, depth }. |
efx:toggle | Branch folded or unfolded. detail = { label, expanded }. |
chart-venn
2.9 KBArea-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.
Venn as a card background.
[{"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.| Class | What it does |
|---|---|
efx-chart-venn | Renders a 2- or 3-set Venn from region sizes. |
| Attribute | Default | Values |
|---|---|---|
data-efx-data | JSON regions [{"sets":["A"],"size":12},{"sets":["A","B"],"size":4}]. | |
data-efx-opacity | 0.4 | Circle fill opacity. |
data-efx-height | 300 | Chart height in px (0 = element CSS height). |
data-efx-colors | Shine tones | One color per set "#f43f5e|#8b5cf6|#10b981". |
data-efx-prefix / suffix / compact / decimals | Number formatting of the counts. | |
data-efx-tooltip / animate | true | Turn parts off. |
data-efx-background | false | Decorative: just the circles, behind the content. |
data-efx-title | Accessible name (else aria-label or first heading). |
| CSS variable | Default | Controls |
|---|---|---|
--efx-chart-1 … 3 | Shine tones | Set colors. |
--efx-chart-bg-opacity | .35 | Opacity in background mode. |
| Event | When |
|---|---|
efx:select | Region clicked / Enter pressed. detail = { index, label, value }. |
efx:data (listen) | Dispatch on the chart with detail = a regions array to update it. |
viz-arc
2.2 KBNodes on a line, links drawn as arcs above it. Hover a node to highlight its arcs, hover an arc for its endpoints and value.
{"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}]}| Class | What it does |
|---|---|
efx-viz-arc | Renders an arc diagram from graph JSON. |
| Attribute | Default | Values |
|---|---|---|
data-efx-data | Graph JSON (see data format). | |
data-efx-sort | Order nodes by "group" or "degree" (default: input order). | |
data-efx-radius | 5 | Base node radius. |
data-efx-height | 280 | Chart height in px. |
data-efx-colors | Shine tones | Group colors. |
data-efx-tooltip / animate | true | Turn parts off. |
data-efx-background | false | Decorative: fills the element behind its content. |
data-efx-title | Accessible name. |
| CSS variable | Default | Controls |
|---|---|---|
--efx-chart-1 … 7 | Shine tones | Group palette. |
| Event | When |
|---|---|
efx:select | Node or arc clicked / Enter. detail = { index, label, value, series }. |
efx:data (listen) | Dispatch with a new graph { nodes, links } as detail. |
viz-rank
2.3 KBBump 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.
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.| Class | What it does |
|---|---|
efx-viz-rank | Renders a bump or slope chart. |
| Attribute | Default | Values |
|---|---|---|
data-efx-mode | bump | <code>bump</code> (ranks over periods) or <code>slope</code> (first vs last period). |
data-efx-data | Items and values (see data format). | |
data-efx-labels | Period names: "2023|2024|2025". | |
data-efx-ranks | false | Values are already ranks (1 = best). |
data-efx-smooth | true | Curved connectors (false = straight). |
data-efx-height | Chart height in px. | |
data-efx-colors | Shine tones | Colors "#f43f5e|#8b5cf6". |
data-efx-prefix / suffix | Value formatting, e.g. "$" or "%". | |
data-efx-compact / decimals / format | 12.3k style, fixed decimals, or a registered formatter name. | |
data-efx-legend / tooltip / animate | true | Turn parts off. |
data-efx-background | false | Decorative: fills the element behind its content (no axes/tooltip). |
data-efx-title | Accessible name (else aria-label or first heading). |
| CSS variable | Default | Controls |
|---|---|---|
--efx-chart-1 … 7 | Shine tones | Palette. |
--efx-chart-grid / --efx-chart-text | muted | Gridlines and axis labels. |
--efx-chart-bg-opacity | .35 | Opacity in background mode. |
| Event | When |
|---|---|
efx:select | Item clicked / Enter pressed. detail = { index, label, value, series }. |
efx:data (listen) | Dispatch with detail { labels, series } to update. |
viz-chord
2.2 KBChord diagram: outer arcs per group, ribbons sized by flow between groups. Hover a group to highlight its ribbons, hover a ribbon for both directions.
{"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.| Class | What it does |
|---|---|
efx-viz-chord | Renders a chord diagram from a square matrix. |
| Attribute | Default | Values |
|---|---|---|
data-efx-data | Matrix JSON (see data format). | |
data-efx-labels | Group labels "A|B|C". | |
data-efx-gap | 0.04 | Gap between groups in radians. |
data-efx-height | 380 | Chart height in px. |
data-efx-colors | Shine tones | Group colors. |
data-efx-prefix / suffix / compact | Value formatting. | |
data-efx-tooltip / animate | true | Turn parts off. |
data-efx-background | false | Decorative: fills the element behind its content. |
data-efx-title | Accessible name. |
| CSS variable | Default | Controls |
|---|---|---|
--efx-chart-1 … 7 | Shine tones | Group palette. |
| Event | When |
|---|---|
efx:select | Arc or ribbon clicked / Enter. detail = { index, label, value }. |
efx:data (listen) | Dispatch with { labels, matrix } as detail. |
viz-pack
3.4 KBNested 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.
{"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}]}]}| Class | What it does |
|---|---|
efx-viz-pack | Renders circle packing from hierarchy JSON. |
| Attribute | Default | Values |
|---|---|---|
data-efx-data | Hierarchy JSON (see data format). | |
data-efx-padding | 0.15 | Gap between circles, as a fraction of the average leaf radius. |
data-efx-height | 420 | Chart height in px. |
data-efx-colors | Shine tones | Colors for top-level branches. |
data-efx-prefix / suffix / compact | Value formatting. | |
data-efx-tooltip / animate | true | Turn parts off (animate off = instant zoom). |
data-efx-background | false | Decorative: fills the element behind its content. |
data-efx-title | Accessible name. |
| CSS variable | Default | Controls |
|---|---|---|
--efx-chart-1 … 7 | Shine tones | Branch palette. |
| Event | When |
|---|---|
efx:select | Circle clicked / Enter (also zooms). detail = { index, label, value, series }. |
efx:data (listen) | Dispatch with a new hierarchy as detail. |
viz-distribution
3.2 KBGaussian-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.
median latency
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.| Class | What it does |
|---|---|
efx-viz-distribution | Renders a distribution plot; pick the shape with data-efx-mode. |
| Attribute | Default | Values |
|---|---|---|
data-efx-mode | density | <code>density</code> (overlaid curves) · <code>violin</code> · <code>ridgeline</code> · <code>beeswarm</code>. |
data-efx-data | Samples as JSON (see data format). | |
data-efx-labels | Group names: "Fri|Sat|Sun". | |
data-efx-names | Series names. | |
data-efx-bandwidth | auto | KDE bandwidth in value units (default: Silverman rule of thumb). |
data-efx-overlap | 0.8 | Ridgeline: how far peaks rise into the row above (0 = none). |
data-efx-grid | true | Gridlines. |
data-efx-height | Chart height in px. | |
data-efx-colors | Shine tones | Colors "#f43f5e|#8b5cf6". |
data-efx-prefix / suffix | Value formatting, e.g. "$" or "%". | |
data-efx-compact / decimals / format | 12.3k style, fixed decimals, or a registered formatter name. | |
data-efx-legend / tooltip / animate | true | Turn parts off. |
data-efx-background | false | Decorative: fills the element behind its content (no axes/tooltip). |
data-efx-title | Accessible name (else aria-label or first heading). |
| CSS variable | Default | Controls |
|---|---|---|
--efx-chart-1 … 7 | Shine tones | Palette. |
--efx-chart-grid / --efx-chart-text | muted | Gridlines and axis labels. |
--efx-chart-bg-opacity | .35 | Opacity in background mode. |
| Event | When |
|---|---|
efx:select | Curve, 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. |
viz-map
4.0 KBA 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.
Map as a card background
<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).| Class | What it does |
|---|---|
efx-viz-map | Renders a GeoJSON map with optional choropleth, bubbles and routes. |
| Attribute | Default | Values |
|---|---|---|
data-efx-geo / data-efx-geo-url | GeoJSON inline, or a URL to fetch (also inline script JSON). | |
data-efx-projection | mercator | <code>mercator</code>, <code>equirectangular</code> or <code>natural</code> (natural earth). |
data-efx-data | Choropleth values [{id|name, value}] matched to feature.id / properties.name. | |
data-efx-points | Bubbles [{lat, lon, value, label}], radius by sqrt(value). | |
data-efx-routes | Curved animated arcs [{from:[lat,lon], to:[lat,lon]}]. | |
data-efx-steps | 6 | Colour steps in the ramp. |
data-efx-zoom | false | Wheel to zoom, drag to pan, double-click to reset. |
data-efx-colors | Shine tones | First colour = choropleth ramp, second = bubbles and routes. |
data-efx-prefix / suffix / compact / decimals / format | Value formatting. | |
data-efx-height | auto | px; default follows the map aspect ratio. |
data-efx-legend / tooltip / animate | true | Turn parts off. |
data-efx-background | false | Decorative: fills the element behind its content. |
data-efx-title | Accessible name. |
| CSS variable | Default | Controls |
|---|---|---|
--efx-chart-1 … 7 | Shine tones | Palette; ramps mix colour 1 with --sh-surface. |
| Event | When |
|---|---|
efx:select | Region or bubble clicked / Enter pressed. detail = { index, label, value }. |
efx:data (listen) | detail { geo, data, points, routes } replaces any of them. |
viz-marimekko
1.7 KBMosaic 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.
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.| Class | What it does |
|---|---|
efx-viz-marimekko | Renders a Marimekko / mosaic chart. |
| Attribute | Default | Values |
|---|---|---|
data-efx-data | Segments per column (see data format). | |
data-efx-labels | Column names: "Asia|Europe|US". | |
data-efx-names | Segment names. | |
data-efx-inside | percent | Cell labels: <code>percent</code>, <code>value</code> or <code>none</code> (shown only where they fit). |
data-efx-gap | 2 | Pixels between columns. |
data-efx-height | Chart height in px. | |
data-efx-colors | Shine tones | Colors "#f43f5e|#8b5cf6". |
data-efx-prefix / suffix | Value formatting, e.g. "$" or "%". | |
data-efx-compact / decimals / format | 12.3k style, fixed decimals, or a registered formatter name. | |
data-efx-legend / tooltip / animate | true | Turn parts off. |
data-efx-background | false | Decorative: fills the element behind its content (no axes/tooltip). |
data-efx-title | Accessible name (else aria-label or first heading). |
| CSS variable | Default | Controls |
|---|---|---|
--efx-chart-1 … 7 | Shine tones | Palette. |
--efx-chart-grid / --efx-chart-text | muted | Gridlines and axis labels. |
--efx-chart-bg-opacity | .35 | Opacity in background mode. |
| Event | When |
|---|---|
efx:select | Cell clicked / Enter pressed. detail = { index, label, value, series }. |
efx:data (listen) | Dispatch with detail { labels, series } to update. |
viz-network
3.2 KBForce-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.
A live graph drifting behind this card.
{"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"}]}| Class | What it does |
|---|---|
efx-viz-network | Renders a force-directed graph from graph JSON. |
| Attribute | Default | Values |
|---|---|---|
data-efx-data | Graph JSON (see data format). | |
data-efx-label | false | Print node labels (label or id). |
data-efx-zoom | true | Wheel zoom and background pan. |
data-efx-link-distance | 70 | Preferred link length in px. |
data-efx-charge | 60 | Repulsion strength between nodes. |
data-efx-radius | 5 | Average node radius. |
data-efx-height | 420 | Chart height in px. |
data-efx-colors | Shine tones | Group colors "#f43f5e|#8b5cf6". |
data-efx-tooltip / animate | true | Turn parts off (animate off = static layout). |
data-efx-background | false | Decorative: fills the element behind its content. |
data-efx-title | Accessible name. |
| CSS variable | Default | Controls |
|---|---|---|
--efx-chart-1 … 7 | Shine tones | Group palette. |
--efx-chart-text | muted text | Link color. |
| Event | When |
|---|---|
efx:select | Node clicked / Enter pressed. detail = { index, label, value, series }. |
efx:data (listen) | Dispatch with a new graph { nodes, links } as detail. |
viz-parallel
2.7 KBOne 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.
Every line is a candidate.
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 }).| Class | What it does |
|---|---|
efx-viz-parallel | Renders parallel coordinates from rows of numeric fields. |
| Attribute | Default | Values |
|---|---|---|
data-efx-data | Rows (see data format). | |
data-efx-dims | all numeric keys | Axes to show, in order: "mpg|hp|weight". |
data-efx-group | group | Row field used for line color and legend. |
data-efx-opacity | 0.65 | Line opacity. |
data-efx-height | Chart height in px. | |
data-efx-colors | Shine tones | Colors "#f43f5e|#8b5cf6". |
data-efx-prefix / suffix | Value formatting, e.g. "$" or "%". | |
data-efx-compact / decimals / format | 12.3k style, fixed decimals, or a registered formatter name. | |
data-efx-legend / tooltip / animate | true | Turn parts off. |
data-efx-background | false | Decorative: fills the element behind its content (no axes/tooltip). |
data-efx-title | Accessible name (else aria-label or first heading). |
| CSS variable | Default | Controls |
|---|---|---|
--efx-chart-1 … 7 | Shine tones | Palette. |
--efx-chart-grid / --efx-chart-text | muted | Gridlines and axis labels. |
--efx-chart-bg-opacity | .35 | Opacity in background mode. |
| Event | When |
|---|---|
efx:select | Line clicked / Enter pressed. detail = { index, label, value, series }. |
efx:data (listen) | Dispatch with detail = rows array or { labels, series } to update. |
viz-wordcloud
2.3 KBWords 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.
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:"…"}.| Class | What it does |
|---|---|
efx-viz-wordcloud | Renders a word cloud from weighted words or raw text. |
| Attribute | Default | Values |
|---|---|---|
data-efx-data | "word:weight|word:weight" or JSON [{text,value}]. | |
data-efx-text | Raw text; words are counted, stop words removed. | |
data-efx-min-size / max-size | 12 / 56 | Font size range in px. |
data-efx-rotate | 0 | Angles to pick from, e.g. "0|90" or "0|-30|30". The biggest word stays at the first angle. |
data-efx-max | 80 | Maximum words shown. |
data-efx-padding | 2 | Gap between words in px. |
data-efx-height | auto | Chart height in px (default half the width, min 200). |
data-efx-colors | Shine tones | Palette "#f43f5e|#8b5cf6", cycled by rank. |
data-efx-tooltip / animate | true | Turn parts off. |
data-efx-background | false | Decorative: fills the element behind its content. |
data-efx-title | Accessible name. |
| CSS variable | Default | Controls |
|---|---|---|
--efx-chart-1 … 7 | Shine tones | Palette. |
| Event | When |
|---|---|
efx:select | Word clicked / Enter pressed. detail = { index, label, value }. |
efx:data (listen) | Dispatch with detail { words:[{text,value}] } or { text } to update. |