Source Code

<div class="app">
  <div class="card">
    <div class="card-header">
      <h3>Traffic Sources, Last 12 Months</h3>
      <p class="sub">A stacked area chart with a centered "wiggle" baseline instead of a flat zero line — the flowing shape emphasizes change in each source's share over time.</p>
    </div>
    <div class="chart-wrap">
      <svg id="stream" viewBox="0 0 640 360" xmlns="http://www.w3.org/2000/svg"></svg>
    </div>
    <div class="legend" id="legend"></div>
  </div>
</div>

Streamgraph Chart — Centered Wiggle Stacked Area SVG

Streamgraph Chart · Charts · Plain HTML, CSS & JS · Live preview

What's included

Features

Centered "wiggle" baseline recenters the whole stack around the vertical middle instead of a flat zero line
Inside-out stack ordering places higher-average series toward the visual center for a calmer silhouette
Quadratic-bezier midpoint smoothing rounds every band's edges with no curve-interpolation library
Each band renders as one closed SVG path built from its smoothed top and reversed bottom edges
Hover isolation dims every band except the hovered one, synced between the chart and the legend
Native SVG title tooltips report each series' average share on hover
Deterministic pseudo-random noise layered onto a sine wave produces realistic-looking synthetic monthly data
Interactive legend with matching swatch colors doubles as a hover-to-isolate control

About this UI Snippet

Streamgraph Chart — Centered Wiggle Baseline & Inside-Out Stack Ordering in Hand-Drawn SVG

Screenshot of the Streamgraph Chart snippet rendered live

A streamgraph is a stacked area chart that has been recentered around a floating middle baseline instead of a flat zero line, producing an organic, flowing river-like shape rather than rigid stacked blocks. This snippet renders five synthetic traffic-source series across twelve months as a streamgraph, computing the centered stack and smoothed band outlines entirely from scratch in inline SVG — no stacked area chart library, no D3.

Why a centered baseline changes what the shape communicates

An ordinary stacked area chart accumulates every series upward from y = 0, which makes the *total* easy to read but makes an individual series' own ups and downs hard to see once it's buried in the middle of the stack — a shrinking band surrounded by growing ones can look deceptively flat. A streamgraph instead computes, for every time step, cursor = -total[i] * scale / 2 as the starting point, centering the *entire stack* around the vertical middle rather than the bottom edge. Every band's thickness at any x position still represents its value exactly like before, but the whole ribbon now visibly drifts, swells, and narrows as a connected organic form, which is what makes relative change between series easier to perceive at a glance.

Inside-out ordering keeps the widest bands in the middle

The stacking order itself matters for how calm the resulting silhouette looks. This snippet sorts series by their average value, then alternately pushes each one to the front or the back of a stackOrder array (i % 2 === 0 pushes, otherwise unshifts) — the classic "inside-out" ordering used by most streamgraph implementations, which places the largest-average series toward the visual center and the smallest toward the outer edges. Without this step, a chart stacked in an arbitrary or alphabetical order tends to look far more jagged, since large and small bands end up interleaved unpredictably.

Smoothing without a curve-interpolation library

Charting libraries typically offer a named curve type (curveBasis, curveCardinal) for this look. This snippet instead builds smoothPath() directly: for each pair of adjacent points, it draws a quadratic Bézier curve (Q) from the current point toward the midpoint between it and the next point, which is a simple, dependency-free way to round off the sharp corners a raw polyline would otherwise have between monthly data points, producing the soft, flowing edges characteristic of the streamgraph look.

One path per band, hover to isolate

Each series renders as a single closed SVG <path> — its smoothed top edge followed by its smoothed bottom edge reversed, closing into one shape — filled with that series' color. Hovering either a band or its legend entry dims every other band via a shared setActive() function, so a viewer can trace one series' contribution through the flowing stack without the surrounding bands visually competing for attention.

Build with AI

Build, Understand, Optimize, and Extend It With AI

Paste this snippet's HTML, CSS, and JS into an AI coding assistant like Claude and ask it to explain exactly how centering the stack around a floating baseline differs mathematically from a normal bottom-up stacked area chart, and why the inside-out ordering (placing higher-average series toward the center) produces a calmer silhouette than an arbitrary stacking order. It's also a good candidate for extension — ask it to add a click-to-pin interaction that keeps one band isolated after the mouse leaves, animate the transition when swapping in a new dataset so bands morph smoothly rather than snapping, or replace the quadratic-bezier smoothing with a proper Catmull-Rom-to-bezier conversion for an even softer curve through the exact data points.

Prompt to recreate it

Copy this into your AI assistant of choice to build the effect from scratch, or as a jumping-off point for your own variant:

text
Build a streamgraph chart in plain HTML, CSS, and JavaScript using inline SVG created with createElementNS — no charting library, no canvas.

Requirements:
- At least five time-series categories, each with a numeric value at every one of at least ten shared time steps (months). Generate realistic synthetic values per category (e.g. a base level plus a smooth periodic wave plus a small amount of noise) if no real dataset is supplied.
- Implement centered "wiggle" stacking: at each time step, compute a starting offset equal to negative half of that time step's total across all series, then stack every series' band upward from that shared centered offset — rather than stacking upward from a flat zero baseline like an ordinary stacked area chart.
- Implement inside-out stack ordering: sort the series by their average value, then build a final stacking order by alternately placing each series toward the front or the back of the order, so higher-average series end up positioned toward the visual center of the stack.
- Smooth each band's top and bottom edges using quadratic Bézier curve segments between consecutive points (drawing each curve toward the midpoint of each adjacent point pair) rather than straight polylines, and close each band into one filled SVG path combining its smoothed top edge and its smoothed, reversed bottom edge.
- Add hover interactivity: hovering a band, or hovering a corresponding legend entry, must dim every other band (and every other legend entry) so the hovered series' shape is easy to isolate and trace through the whole time range.
- Include a legend with a color swatch per series, and label the x-axis with the time step names beneath the chart.

Want to tighten it up first? Run this prompt through the AI Prompt Studio to score it across 8 quality dimensions, catch anti-patterns, and tune the wording for Claude, ChatGPT, or Gemini before you paste it in.

Step by step

How to Use

  1. 1
    Read a band's thickness over timeAt any x position, a band's vertical thickness represents that series' value at that time step — exactly like a normal stacked area chart, just recentered.
  2. 2
    Hover a band or legend entryHovering isolates one series by dimming every other band, making it easy to trace a single series' shape through the flowing stack.
  3. 3
    Compare relative movementBecause the whole stack floats around a centered baseline, a series swelling or narrowing is visible as motion in the ribbon shape itself, not just a subtle shift buried inside a flat-bottomed stack.
  4. 4
    Swap in real dataReplace the SERIES array's base/amp/phase values (or the buildSeries() function entirely) with your own real time-series values per category.
  5. 5
    Adjust the smoothingEdit smoothPath() in the JS panel — using a different midpoint fraction or a cubic Bézier instead of quadratic changes how tightly the bands hug the raw data points.
  6. 6
    Change the stack orderEdit the inside-out sort/alternate logic that builds stackOrder to try a different visual arrangement of which series sits toward the center.

Real-world uses

Common Use Cases

Traffic source and channel-mix trends
Show how the relative contribution of several marketing or traffic channels shifts over many months in one flowing shape.
Topic or category volume over time
Visualize how the relative popularity of several categories, tags, or topics rises and falls across a long time span.
Executive and trend-reporting dashboards
A streamgraph reads as a single organic trend at a glance, useful where a stacked area chart or stacked bar chart would feel too rigid for a high-level summary.
Teaching stack centering and path smoothing
A concrete, from-scratch implementation of the centered-baseline stacking math and quadratic-bezier smoothing technique.
Reference for dependency-free flowing SVG charts
The stacking, ordering, and smoothing functions here are small and reusable in any project needing an organic multi-series chart without a charting library.

Got questions?

Frequently Asked Questions

A regular stacked area chart accumulates every series upward from a flat y = 0 baseline. A streamgraph instead centers the entire stack around the vertical middle at every time step, computing each band's starting position as negative half of that time step's total. The band thicknesses represent the same values either way, but the centered version produces a flowing, organic shape rather than blocks stacked from a fixed floor.

It refers to sorting series by their average value and then alternately placing each one toward the front or back of the stacking order, so the series with the largest average values end up positioned toward the visual center of the stack and the smallest toward the outer edges. This produces a noticeably calmer, more balanced silhouette than stacking series in an arbitrary or alphabetical order.

smoothPath() walks each band's array of points and, between every consecutive pair, draws a quadratic Bézier curve command (Q) toward the midpoint of that pair rather than a straight line — a simple, dependency-free technique that rounds off the sharp corners a raw polyline would otherwise have at each data point.

A closed path — the smoothed top edge followed by the smoothed bottom edge in reverse, then closed with Z — is what lets the band be filled as one solid colored shape. Drawing the top and bottom as two open, unfilled lines would only show outlines, not the solid ribbon that makes a streamgraph readable.

Yes — replace buildSeries() entirely, or just the values array on each entry in SERIES, with your own real per-time-step numeric values. Everything downstream (stacking, centering, smoothing, rendering) works on whatever values array each series provides.

Yes. Use the JSX, Vue, Angular, or Tailwind export buttons on this page. In React, compute the stacking and smoothed path strings during render (memoized with useMemo, since recomputation is proportional to series count times time steps) and render the resulting paths from state.