Home / Distribution / Beeswarm Plot
Beeswarm Plot in HTML, CSS and JavaScript
A beeswarm plot shows every single data point as a dot, placed along an axis and nudged sideways so no two dots overlap. This free template draws one with plain SVG and vanilla JavaScript, no chart library. The example shows finish times for 300 marathon runners.
What is a beeswarm plot?
A beeswarm plot shows every single data point as a dot, placed along an axis and nudged sideways so no two dots overlap. Where many values are close together, the dots pile up into a swarm.
It gives you the shape of a histogram and the detail of every point at the same time. People like it because each dot is a real person, order or event they can point at.
At a glance
- Best for
- Showing every value while keeping the shape
- Data you need
- A list of numbers, up to a few hundred
- Skip it when
- Thousands of points. Use a histogram.
- Made with
- HTML, CSS and vanilla JavaScript. No library.
When to use a beeswarm plot
- Race or exam results
- Prices of every product in a range
- Survey answers where each person matters
- Stories about people, like ages of members
When to pick another chart
- Histogram: you have thousands of values
- Strip Plot: you want several groups on separate rows
What you get in this template
- 300 dots placed without overlap by a simple layout in plain JavaScript
- Dots colored by age group
- Hide an age group from the key and the swarm rebuilds
- A line marking four hours
- Times shown as hours and minutes
- A summary table for each age group
How the code works
Here is a short version of the idea behind this beeswarm plot. The full file adds the axis, labels, tooltips, sorting and resizing on top of it.
const times = [238, 241, 239, 250, 244, 262, 240, 246, 243, 255];
const x = t => 40 + (t - 200) * 7, r = 6, mid = 150;
const placed = [];
times.slice().sort((a, b) => a - b).forEach(t => {
let y = mid;
for (let k = 1; placed.some(p => Math.hypot(p[0] - x(t), p[1] - y) < r * 2); k++) {
y = mid + (k % 2 ? 1 : -1) * Math.ceil(k / 2) * r; // try above, then below
}
placed.push([x(t), y]);
drawCircle(x(t), y, r, '#38bdf8');
});The example uses four tiny helpers that create SVG shapes. Put them above the code and it runs as is.
const svg = document.querySelector('svg');
function make(tag, attrs) {
const n = document.createElementNS('http://www.w3.org/2000/svg', tag);
for (const k in attrs) n.setAttribute(k, attrs[k]);
svg.appendChild(n);
return n;
}
function drawRect(x, y, width, height, fill) { return make('rect', { x, y, width, height, fill }); }
function drawCircle(cx, cy, r, fill) { return make('circle', { cx, cy, r, fill }); }
function drawLine(x1, y1, x2, y2, stroke, width, dash) {
return make('line', { x1, y1, x2, y2, stroke, 'stroke-width': width || 1, 'stroke-dasharray': dash || 'none' });
}
function drawText(x, y, str, anchor) {
const t = make('text', { x, y, 'text-anchor': anchor || 'start' });
t.textContent = str;
return t;
}How to add it to your website
- Download the file. Click Download HTML file above. You get one file called beeswarm-plot.html with everything inside.
- Change the data. Open the file in any code editor and find the DATA list near the bottom. Replace the names and numbers with your own.
- Change the colors and text. Colors are at the top of the style tag. The title, subtitle and main point are plain HTML near the top of the body.
- Put it online. Upload the file to any host, such as GitHub Pages, Netlify or your own server, or paste it into your site. There is no build step.
Questions people ask
What is a beeswarm plot?
A beeswarm plot is a chart where every value is a dot along an axis, moved sideways just enough to avoid overlapping. The pile of dots shows where values are common.
How many points can a beeswarm plot show?
A few hundred works well. With thousands, the swarm gets too tall or the dots too small, and a histogram is clearer.
What is the difference between a beeswarm and a strip plot?
A strip plot scatters dots randomly and they can overlap. A beeswarm places each dot carefully so none overlap, which looks neater and shows the shape better.
Does the sideways position mean anything?
No. Only the position along the main axis carries the value. The sideways spread is just there to stop dots covering each other.
More distribution

031. Histogram
Example: delivery times for 600 pizza orders
032. Box Plot
Example: monthly rent for flats in six neighborhoods
033. Violin Plot
Example: coffee order waits at four cafes
034. Density Plot
Example: sunflower heights with and without plant feed
035. Ridgeline Plot
Example: daily high temperatures for each month of the year
037. Strip Plot
Example: train delays on five lines over 60 weekdays
038. Population Pyramid
Example: the age of a town in 2006 and 2026
039. Error Bar Chart
Example: battery life test results for five phones