Box Plot — HTML CSS JS Box-and-Whisker (No Library)

Box Plot · Charts · Plain HTML, CSS & JS · Live preview

Share & Support

What's included

Features

Five-number summary
Computes Q1, median, and Q3 with linear-interpolation quantiles from raw data.
Tukey IQR fences
Whiskers stop at the most extreme points within 1.5x IQR, not the absolute extremes.
Outlier dots
Points beyond the fences are drawn individually as red circles.
Translucent quartile box
A Q1 to Q3 box in the group colour with a bold median line across it.
Shared comparison axis
All groups use one y-scale from the combined range, so distributions compare directly.
Gridlines and ticks
Reference levels and axis labels make values readable.
Five-number tooltip
Hovering a box shows min, Q1, median, Q3, and max.
Data-driven & no library
Computes and draws from a GROUPS array of raw samples in plain HTML/CSS/SVG/JS.

About this UI Snippet

Box Plot — Quartiles, IQR Whiskers, and Outliers Computed from Raw Data

Screenshot of the Box Plot snippet rendered live

A box plot (box-and-whisker) is the standard way to summarise a distribution: the box spans the middle 50% of values, a line marks the median, whiskers reach the typical range, and dots flag outliers. It compares spread and skew across groups far better than a bar of averages. This snippet builds it in plain HTML, CSS, SVG, and vanilla JavaScript, computing all the statistics from raw samples itself — no charting library.

It computes the real statistics

Given a raw array of numbers per group, stats() sorts them and derives the five-number summary using linear-interpolation quantiles: Q1 (25th percentile), the median (50th), and Q3 (75th). From those it computes the interquartile range (IQR = Q3 − Q1) and the Tukey fences at 1.5×IQR beyond each quartile. This quantile-and-IQR math is the heart of a box plot, and doing it from raw data (rather than pre-computed values) is what makes it a genuine statistical chart rather than a styled bar.

Whiskers that stop at the data, plus outliers

A correct box plot does not run its whiskers to the absolute min and max — it runs them to the most extreme points still *within* the 1.5×IQR fences, and draws anything beyond as individual outlier dots. The snippet filters the sorted data by the fences to find the whisker ends, then plots the out-of-fence points as red circles. This Tukey convention is the detail most hand-rolled box plots get wrong (running whiskers to the extremes hides outliers); getting it right is what makes the chart trustworthy.

Drawn as labelled SVG glyphs

Each group renders as a vertical whisker line with end caps, a translucent box from Q1 to Q3 in the group colour, a bold median line across it, and outlier dots — all positioned by a shared y() scale mapping data values to pixels (rounded to a clean axis range). Gridlines and axis ticks give reference levels, and a label sits under each box. Because the box is its own SVG node, hovering it shows the full five-number summary in a tooltip.

A shared axis for comparison

All groups share one y-axis computed from the combined data range, so their boxes are directly comparable — you can see at a glance which class has the higher median, the wider spread, or the skew (median off-centre in its box). Comparing distributions side by side on one scale is the main reason to use box plots over separate summaries.

Data-driven and drop-in

Feed it any array of { name, color, data } with raw samples and it computes and draws the plot. It is a clear, dependency-free reference for the quartile, IQR, whisker, and outlier math behind every box-and-whisker chart.

Build with AI

Build, Understand, Optimize, and Extend It With AI

You don't have to re-derive the quantile interpolation or the Tukey fence math by hand to trust this chart. Paste this snippet's HTML, CSS, and JS into an AI coding assistant like Claude and ask it to explain exactly how the quantile function interpolates between two sorted values to compute Q1, the median, and Q3, and why the whiskers are drawn from the most extreme in-fence points rather than the raw min and max. The same assistant can help optimize it — asking whether re-sorting each group's full array on every render() call matters at scale, or whether the SVG could be rebuilt incrementally instead of clearing innerHTML and rebuilding every node on each redraw. It's also useful for extending the chart: ask it to add notched boxes for a visual confidence-interval indicator, support horizontal box plots, or animate the box and whiskers growing in on load. Treat the code less like a finished artifact and more like a starting point for a conversation.

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 "box-and-whisker plot" that computes real statistics from raw sample arrays in plain HTML, CSS, and SVG built with vanilla JavaScript — no charting library, no pre-computed quartiles supplied by the caller.

Requirements:
- Accept input as a plain array of groups, each with a name, a color, and a raw array of numeric samples (not pre-computed statistics).
- Compute Q1, median, and Q3 per group using linear-interpolation quantiles on the sorted sample array (interpolating between the two nearest ranked values, not simple nearest-rank).
- Compute the interquartile range and Tukey fences at 1.5 times the IQR beyond Q1 and Q3, and draw the whiskers only out to the most extreme sample values that still fall within those fences — never to the raw dataset minimum and maximum.
- Draw every sample outside the fences as its own individually plotted outlier point, distinct in color from the box and whiskers.
- Render each group as: a vertical whisker line with horizontal end caps, a semi-transparent rectangle spanning Q1 to Q3 in the group's color, and a bold horizontal median line drawn across the box at the correct height.
- Use one shared y-axis scale computed from the combined minimum and maximum across all groups (rounded to a clean range) so every group's box is positioned on a directly comparable scale, with gridlines and axis tick labels.
- On hovering a box, show a tooltip listing that group's name, minimum, Q1, median, Q3, and maximum, positioned near the cursor.

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
    Paste HTML, CSS, and JSA box plot renders for three classes, each computed from its raw scores.
  2. 2
    Read the boxesThe box is the middle 50% (Q1 to Q3), the bold line is the median, whiskers reach the IQR range.
  3. 3
    Spot outliersRed dots beyond the whiskers are values outside the 1.5x IQR fences.
  4. 4
    Hover a boxSee the full five-number summary (min, Q1, median, Q3, max) in a tooltip.
  5. 5
    Swap in your dataReplace the GROUPS array with your own { name, color, data } raw samples.
  6. 6
    Wire to an APIFetch your samples, map them into GROUPS, and call render().

Real-world uses

Common Use Cases

Comparing distributions
Compare spread and skew across groups — pair with a histogram for one group's shape.
Test scores and grades
Show score distributions per class or cohort alongside a bar chart of averages.
Performance and latency
Visualise response-time spread and outliers across services.
Experiment and A/B results
Compare outcome distributions between variants.
Scientific and survey data
Summarise sample distributions with quartiles and outliers.
Learning quartile math
A reference for IQR, whiskers, and outlier detection — compare with a scatter plot.

Got questions?

Frequently Asked Questions

stats() sorts the raw data and uses linear-interpolation quantiles: for a percentile q, it finds the fractional position q × (n − 1), then interpolates between the two surrounding sorted values. This gives Q1 (q=0.25), the median (0.5), and Q3 (0.75). It is the same method most statistical tools use, and computing from raw samples is what makes this a real box plot rather than a styled bar.

By the standard Tukey convention, whiskers extend only to the most extreme data points still within 1.5x the interquartile range beyond Q1 and Q3 (the fences). Anything past the fences is an outlier, drawn as its own dot. Running whiskers to the absolute extremes would hide outliers, which defeats the purpose — so the snippet filters by the fences to find the whisker ends and plots the rest as outlier circles.

The box spans Q1 to Q3 — the middle 50% of the data — so a taller box means more spread. The median line shows the centre; when it sits off-centre within the box, the distribution is skewed toward the longer side. Comparing boxes across groups on the shared axis reveals differences in centre, spread, and skew that an average alone would hide.

Edit the GROUPS array — each entry is { name, color, data } where data is the raw sample array. Add, remove, or change groups and the quartiles, whiskers, outliers, shared axis, and labels all recompute on the next render(). For real data, fetch your samples, map them into that shape, and call render(); the layout adapts to any number of groups.

In React, hold the groups in state and compute stats with useMemo, rendering the SVG glyphs from them (or run render() in a useEffect with a ref); in Vue, use a computed stats array with v-for; in Angular, a getter with *ngFor. The quantile/IQR/outlier math is framework-agnostic and ports unchanged.