# How to Make a Swarm Plot in Figma (Every Point, Nothing Hidden)
_August 27, 2026 · 11 min read · by Systergon_
> A swarm plot draws every observation and nudges points sideways just enough that none overlap — the honest middle ground between a histogram that bins your data away and a box plot that reduces it to five numbers. Where the sideways offset means nothing and readers assume it does, and the sample sizes at which it works.
Tags: Figma, Charts, Swarm Plot, Distributions, Plugin
URL: https://systergon.com/blog/figma-charts-swarm-plot
---
[Install Figma Charts — it’s free to try →](https://www.figma.com/community/plugin/1345221583582136577/figma-charts) [See the swarm gallery →](https://systergon.com/figma-charts/chart-types/swarmplot)

A swarm plot draws **every observation** as a point, positioned by value and nudged sideways just enough that nothing overlaps. It is the honest middle ground between a [histogram](https://systergon.com/blog/figma-charts-histogram), which bins your data away, and a [box plot](https://systergon.com/blog/figma-charts-box-plot), which summarises it into five numbers — and unlike both, it hides nothing.

![A swarm plot drawn by Nivo inside the Figma Charts plugin](https://systergon.com/blog/figma-charts-swarm-plot/images/swarm-nivo.svg)

_Real plugin output: a Nivo swarm plot captured from the editor. Every chart on this page is the library’s own drawing._

The shape of the swarm _is_ the distribution: where points bunch, the values are common; where the column pinches, they are rare. This page is about when showing everything is better than summarising it, and about the sideways offset — which is decoration in the sense that it carries no data, and essential in the sense that without it there is no chart.

## First — get the plugin

Everything below happens inside **Figma Charts**, a Figma plugin. It runs the real JavaScript charting libraries — Google Charts, Highcharts, D3-based Nivo, ApexCharts and Apache ECharts — inside the plugin window, so the packing on your canvas is the library’s own collision algorithm.

[Install Figma Charts from the Figma Community →](https://www.figma.com/community/plugin/1345221583582136577/figma-charts)

Press **⌘/** (**Ctrl /** on Windows), type _Figma Charts_, hit Enter, and pick **Swarm Plot** from the category filter. One example, from Nivo — and two close relatives elsewhere, covered [below](#relatives).

## The sideways offset carries no data, and that is fine

In a swarm plot, one axis is your measurement and the other is **nothing at all** — it exists purely so that points which share a value have somewhere to sit. Three ways of doing that offset, and they are not equivalent:

- **Jitter** adds a small random displacement. Quick, universally available, and it makes the density approximate: a cluster looks like a cloud rather than a shape.
- **Beeswarm packing** places each point as close to the centre line as it can without touching a neighbour. Deterministic, tidy, and the resulting silhouette is a genuine density curve made of dots.
- **Binned columns** — grouping values into bins and stacking the points in each — produces the histogram-of-dots look, exact and slightly blocky.

All three encode the same data; they differ in how honestly the width reads as density. A beeswarm is the version worth reaching for, and it is what Nivo’s implementation does.

## Two relatives that do part of the job

![A jittered scatter plot of exam scores by subject drawn by Highcharts](https://systergon.com/blog/figma-charts-swarm-plot/images/swarm-jitter.svg)

_**Jitter** — the same idea via a random offset, available in Highcharts as an option on any scatter series. It is the pragmatic version: one setting, no new chart type, and a slightly noisier picture of the same distribution._

![A dot plot chart drawn by Highcharts](https://systergon.com/blog/figma-charts-swarm-plot/images/swarm-dotplot.svg)

_**The dot plot** — one point per category rather than one per observation. It is the summarised cousin: excellent for comparing a handful of values, and it discards the individual data the swarm exists to show._

## When a swarm plot is right, and when it is not

**Use it when** you have between about twenty and a few hundred observations per group, when the shape of the distribution matters, and when individual points are worth seeing — especially when someone will ask about a specific one.

Three cases where something else wins:

**1. Thousands of points per group.** The packing runs out of room, points spill wide, and the chart becomes a solid blob that no longer reads as a distribution. Above a few hundred, a [histogram](https://systergon.com/blog/figma-charts-histogram) or a violin plot summarises better.

**2. Many groups.** Each group needs horizontal room for its widest point. Six or eight columns is comfortable; twenty is a wall of dots.

**3. Precise values matter.** Reading a point’s value against an axis is fine; comparing two points in different columns is not, because the eye has to travel. If the comparison is the task, plot the summary statistics.

A fourth worth naming: **when the data is confidential.** A swarm shows every observation, so with small groups a reader can often identify individuals — salaries by team, performance by person. That is a real privacy consideration and the reason a box plot is sometimes the right answer even when a swarm would be more informative.

## The case for showing every point

Every other distribution chart in this series throws something away, and it is worth being explicit about what a swarm keeps.

**Bimodality.** Two clusters with a gap between them is invisible in a box plot — the median lands in the gap — and visible immediately in a swarm. This is the single most common hidden feature in real data, and it usually means two populations have been mixed.

**Granularity and rounding.** Values that pile up on round numbers — exactly 30 minutes, exactly 100 — show up as vertical stripes in a swarm. That is a data-collection artefact worth knowing about, and no summary chart reveals it.

**Sample size, honestly.** Forty points look like forty points. A box plot drawn from nine observations looks exactly as authoritative as one drawn from nine thousand, which is the quietest way a distribution chart misleads.

**The individuals.** When someone asks “which customer is that?”, a swarm has an answer and a histogram does not. In review meetings that question comes up constantly, and being able to point at a dot is worth more than a tidier chart.

## Building one, step by step

Six screens, start to finish, captured from the plugin.

![The Figma Charts gallery filtered to the Swarm Plot category](https://systergon.com/blog/figma-charts-swarm-plot/images/step-gallery.webp)

_**1. Filter to Swarm Plot.** Nivo has the only example. For a jittered scatter, look under Scatter in Highcharts — it is a series option rather than a chart type._

![The Figma Charts editor with a swarm plot in the preview](https://systergon.com/blog/figma-charts-swarm-plot/images/step-editor.webp)

_**2. The editor.** Live preview above, tabs below. Swarms need width per group: check how many groups fit before styling, because the packing spreads sideways and columns collide before points do._

![The Data tab showing the observations behind a swarm plot](https://systergon.com/blog/figma-charts-swarm-plot/images/step-data.webp)

_**3. One row per observation.** A group label and a value, one row each — raw data rather than summaries. Nivo edits this as JSON, because the structure carries group definitions alongside the points._

![The Configuration tab showing swarm plot option groups](https://systergon.com/blog/figma-charts-swarm-plot/images/step-config.webp)

_**4. Configure.** Point size, spacing, the group gap and colour mapping. Point size is the setting that decides how many observations the chart can hold before the packing spills._

![The Export tab showing code export formats](https://systergon.com/blog/figma-charts-swarm-plot/images/step-export.webp)

_**5. Export.** Nivo exports to React, so this chart constrains the handoff — and a jittered scatter is the portable substitute if that is a problem._

![The + SVG and + PNG insert buttons](https://systergon.com/blog/figma-charts-swarm-plot/images/step-insert.webp)

_**6. Insert.** SVG gives you every point as its own vector shape, so labelling one observation — the outlier everyone asks about — is a canvas operation._

## The data shape it needs

Raw observations: a group label and a value per row. That is unusual in this series — most charts take summarised data — and it is the whole point: the chart is doing the summarising visually, so nothing has been decided before it is drawn.

In the plugin, Nivo swarms are a **JSON** shape rather than a table, because the group definitions travel with the points, and **they cannot bind a live data source** — the connection is refused rather than producing a structure the chart cannot render.

Two data notes. **Sample sizes should be comparable**, or one column of forty points sits beside one of four hundred and the wider column looks more important when it is only better attended. State the counts. And **an unparseable value becomes 0**, which in a swarm draws a point at zero — sitting in the column looking like a genuine measurement.

## Library by library

The **Swarm Plot** category holds **one example, in Nivo** — and the technique is available more widely than that suggests.

- **Nivo — 1 example**, and the only true beeswarm here: deterministic packing, configurable point size and spacing, grouping on either axis. React-only export, JSON editing, no live binding.
- **Highcharts — jitter on any scatter series.** Its _Scatter with Jitter_ example is under Scatter, and the option applies to any scatter chart, which makes this the most portable route to the same reading.
- **ECharts — a jittering example, also under Scatter.** Same approach.
- **Google Charts and ApexCharts — no offset option.** The workaround is to add a small random value to the categorical axis in the data itself, which works and means the jitter is baked into your dataset rather than being a display setting.

The distinction worth carrying: **a beeswarm is a chart type, jitter is a setting**. If you need the tidy packed silhouette, that is Nivo. If you need “every observation, roughly placed, in the library my team already uses”, jitter is available nearly everywhere and is usually enough.

As always: **design in whichever library your engineers already use**, because the export then matches production exactly. [Choosing the right chart library](https://systergon.com/blog/figma-charts-choosing-the-right-chart-library) covers the trade-offs.

## Pair it with the summary, not instead of it

The strongest version of this chart is not the swarm alone but the swarm _plus_ a summary drawn over it — a median line, a box, or a violin outline behind the points.

**Why it works:** the summary gives the reader the statistics they will quote, and the points show whether those statistics describe anything real. A median sitting in a gap between two clusters is instantly suspicious in a combined chart and invisible in a box plot.

**What to draw:** a median line is usually enough — it is the number people want and it adds one mark. A full box behind a swarm is a common combination and starts to compete with the points; if you use one, mute it heavily.

**What it costs:** nothing in space, a little in construction — the summary is a second series, so in a static design it is usually a line drawn on the canvas after inserting as SVG. That is a two-minute job and it turns an evocative chart into a defensible one.

## Styling it well

**Small points, some transparency.** Even with collision avoidance, points at the dense middle sit shoulder to shoulder, and a little transparency keeps the silhouette readable rather than solid.

**One colour per group, or one colour overall.** If the groups are already separated by position, colour is free for something else — a subgroup, a flag, a threshold. Colouring the columns differently for no reason spends it on decoration.

**Give each group its own room.** The gap between columns should be clearly larger than the widest point of any swarm, or two groups merge visually into one wide blob.

**Label the axis and the counts.** “Response time (ms)” on the value axis, and “n = 84” under each group name. The counts matter here more than in most charts, because column width already looks like a quantity and is not one.

**Highlight rather than annotate everything.** One or two labelled points — the outlier, the observation being discussed — against a muted swarm reads far better than a field of labels.

For type and colour, bind them to your design system rather than picking by hand — covered in [Your chart, your design system](https://systergon.com/blog/figma-charts-design-system-colors-typography-tokens).

## Vertical or horizontal

Swarms work in both orientations and the choice follows the labels, exactly as it does for bar charts.

**Vertical columns** — value up the y axis, groups across the bottom — is the convention and matches how box plots are drawn, so readers coming from one recognise the other. It suits short group names and a handful of groups.

**Horizontal rows** — value across, groups down the side — gives every group name a full line, which matters when the groups are endpoints, teams or product names. It also lets the chart grow down a scrollable page rather than off the side of a slide.

One asymmetry worth knowing: **horizontal swarms handle more groups**, because vertical space is cheaper than horizontal space in most layouts, while **vertical swarms handle more points per group**, because the packing spreads across the wider dimension. Pick according to which of the two you have more of.

## Reading it well — and the ways it misleads

**Width is not a quantity.** The sideways spread comes from how many points share a value _and_ from the point size and spacing you chose. It reads as density and it is not calibrated, so two swarms with different settings are not comparable.

**Bigger samples make wider swarms.** A group with four hundred observations spreads further than one with forty at the same distribution. Without the counts, readers read the wider column as the bigger phenomenon.

**Packing pushes points off their true value.** A beeswarm keeps the value axis exact and displaces sideways — but some implementations nudge along the value axis to fit. If precision matters, check which yours does.

**Overlap at the edges hides count.** When the swarm is at capacity, extra points are drawn on top of existing ones, so the visible width stops growing while the data keeps arriving. That is the point at which the chart quietly stops being complete.

**Individuals are identifiable.** With small groups, a labelled swarm can expose individual people. That is occasionally the intent and frequently an accident.

## When the swarm gets too big

Swarms fail gracefully into three neighbours, in this order.

**Add transparency and keep going.** Up to a few hundred points, semi-transparent marks let the overlap read as density and the chart survives.

**Switch to a violin plot.** A mirrored density curve shows the same shape as the swarm silhouette without drawing every point, so it scales to thousands. What it loses is the individuals — and, importantly, the honest sense of how much data there is, since a violin drawn from thirty points looks like one drawn from thirty thousand.

**Combine them.** A violin outline with a sampled swarm inside — say two hundred points drawn from the full set — keeps the shape and gives a sense of the individuals, provided you say the points are a sample.

The rule of thumb: **show every point while you honestly can, and say when you stop**. A chart that silently switches from all the data to a summary is where readers lose track of what they are looking at.

## Accessibility

**Point size is an accessibility floor.** Marks below about 4px are hard for many readers to see at all; if the packing needs smaller points, the chart needs fewer observations or more room.

**Do not distinguish subgroups by colour alone.** Shape is available and works well here — circles against triangles survives every form of colour vision deficiency at small sizes.

**Do not hide values in hover.** An inserted SVG has none; label the points that matter directly.

**Give it a text equivalent.** The Export tab’s **Copy Alt Text**, **Copy Data Table** and **Set Node Desc** produce a description, a table of the numbers and a description written onto the Figma node. For a swarm the useful description is the distribution — centre, spread, shape, outliers — plus the count per group.

## Common questions

### What is a swarm plot?

A chart that draws every observation as a point, positioned by value along one axis and nudged sideways so that points do not overlap. The resulting silhouette shows the distribution while keeping every individual data point visible.

### Swarm plot, box plot or histogram?

Swarm when you have tens to a few hundred observations per group and want to show everything. Box plot when you have many groups and need compact comparison. Histogram when you have one distribution and thousands of points. The swarm is the least lossy and the least scalable of the three.

### What is the difference between jitter and a beeswarm?

Jitter offsets each point randomly; a beeswarm packs them deterministically as close to the centre as they will fit. Jitter is available as a setting in most libraries; the beeswarm is a chart type, and it produces a tidier silhouette that reads as a genuine density.

### Which libraries can draw one?

**Nivo** has the only true swarm plot in the plugin. **Highcharts** and **ECharts** both offer jitter on a scatter series, which gets you the same reading with a setting rather than a new chart type. In Google Charts and ApexCharts, add the offset to the data yourself.

### How many points can it hold?

A few hundred per group. Beyond that the packing spills sideways, points start overlapping despite the algorithm, and the chart stops being a faithful picture of the data — which is exactly when a histogram or violin plot takes over.

### Should I add a median line or a box?

A median line, almost always — it gives readers the statistic they will quote while the points show whether it describes anything real. A full box behind the swarm competes with the points; if you use one, mute it heavily.

### Does the width mean anything?

Density, loosely, and it is not calibrated: the spread depends on point size, spacing and sample size as well as on the data. Print the counts so readers do not read a wider column as a larger phenomenon.

### Can I show individual names on the points?

Only a few. Labelling every point turns the chart into a word cloud with axes; labelling the two or three being discussed makes the argument. And with small groups, be deliberate about it — a swarm of salaries by team with names attached identifies individuals, which is occasionally the intent and frequently an accident.

### Does the chart stay editable in Figma?

Insert as **SVG** and every point is its own vector shape — ideal for labelling the one observation the room asks about, and for drawing the median line by hand. Insert as **PNG** for a flat image at twice the pixel density.

## Where to start

Open the plugin, filter to Swarm Plot, put one real group in, and then draw the same group as a box plot beside it. If the box tells the same story, you have a well-behaved distribution and either chart works. If the swarm shows two clusters where the box shows one tidy middle, you have just seen the reason this chart exists.

[Install Figma Charts — it’s free to try →](https://www.figma.com/community/plugin/1345221583582136577/figma-charts) [Browse all 45 chart types →](https://systergon.com/figma-charts/chart-types)