webdevpuneet.com

Pie Chart — HTML CSS JS SVG Pie Chart (No Library)

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

CategoryCharts

Copy & paste

Source Code

<div class="pc-card">
  <div class="pc-head">
    <h3>Traffic by source</h3>
    <span class="pc-total" id="pcTotal"></span>
  </div>
  <div class="pc-body">
    <svg class="pc-svg" id="pcSvg" viewBox="0 0 200 200" role="img" aria-label="Pie chart of traffic by source"></svg>
    <ul class="pc-legend" id="pcLegend"></ul>
  </div>
  <div class="pc-tip" id="pcTip" hidden></div>
</div>

Extend with AI

Take This Snippet Further With AI

The AI prompt for this one is for Patreon supporters ($3 a month, 7 days free), along with a site with no ads. Supporters enter the passcode once and it is remembered in this browser.

· Become a supporter

What's included

Features

Real SVG arc-path slices
Each slice is a computed <path> wedge, so every slice is an interactive DOM node — not a flat conic-gradient.
Correct arc math
Points are derived with cos/sin offset to start at 12 o'clock, with the large-arc-flag set for slices over half the circle.
Hover tooltips
A cursor-following tooltip shows the slice name, raw value, and percentage, positioned via getBoundingClientRect.
Toggleable legend
Clicking a legend row hides or shows a slice and re-proportions the rest, like Chart.js.
Live percentages
Percentages derive from the visible total, so hiding a slice recalculates everyone else's share.
Last-slice guard
The chart prevents hiding the final visible slice so the pie is never empty.
Event delegation
One mousemove and one click listener handle every slice and legend row via closest().
Data-driven & no library
Renders entirely from a DATA array in plain HTML/CSS/SVG/JS — zero dependencies.

About this UI Snippet

Pie Chart — SVG Arc-Path Pie Chart with Hover Tooltips & Toggleable Legend

Screenshot of the Pie Chart snippet rendered live

A pie chart shows part-to-whole composition at a glance — what share each source, category, or segment contributes to a total. This snippet builds a complete, interactive pie chart in plain HTML, CSS, SVG, and vanilla JavaScript, with no charting library: each slice is a real SVG <path> wedge computed from the data, with hover tooltips, a legend that toggles slices on and off, and percentages that recalculate live.

Real SVG wedges, computed with trigonometry

Each slice is an SVG path made of three commands: move to the centre, line out to the start of the arc, then an elliptical A (arc) command sweeping to the end of the slice, then close. The start and end points are found with point(frac), which converts a fraction of the circle (0–1) into x/y coordinates using Math.cos/Math.sin, offset by −90° so the chart starts at twelve o'clock like every pie chart people expect. The arc's large-arc-flag is set to 1 whenever a slice spans more than half the circle, which is the one detail that trips people up when drawing arcs by hand — get it wrong and big slices render inverted.

Why SVG paths instead of conic-gradient

You can fake a pie with a single conic-gradient, but that gives you one flat element with no per-slice interactivity — no hover target, no individual slice to highlight or pull out, no accessible structure. Drawing each slice as its own path means every slice is a real DOM node you can attach a tooltip to, fade on hover, animate independently, or click. That interactivity is the whole point of a chart, so the small amount of arc math is worth it.

A legend that toggles slices

The legend lists every series with its colour swatch and value. Clicking a legend row hides or shows that slice, and the chart re-renders with the remaining slices re-proportioned to the new total — the same behaviour as Chart.js and every dashboard charting tool. A guard prevents hiding the last visible slice (an empty pie is meaningless), and hidden rows stay in the legend, dimmed, so they can be toggled back on. Because the percentages derive from the live total, hiding a slice recalculates everyone else's share automatically.

Tooltips positioned to the cursor

Hovering a slice shows a tooltip with the series name, its raw value, and its percentage, positioned at the mouse using getBoundingClientRect to convert the page coordinates into offsets within the card. The tooltip is pointer-events: none so it never flickers by intercepting its own hover, and it follows the cursor smoothly via a single mousemove listener on the SVG with event delegation through closest('.pc-slice').

Data-driven and drop-in

The entire chart renders from a DATA array of { name, value, color } — swap in your analytics, budget, or survey numbers and everything (slices, legend, total, percentages) updates. Because it's compact and dependency-free, it drops into any dashboard or report, and the arc math is a clear reference for understanding how SVG pie and donut charts are actually drawn.

Step by step

How to Use

  1. 1
    Paste HTML, CSS, and JSA pie chart renders with five slices, a legend, and a running total of visits.
  2. 2
    Hover a sliceMove over any wedge to see a tooltip with its name, value, and percentage of the total.
  3. 3
    Toggle slicesClick a legend row to hide that slice; the remaining slices re-proportion and the total updates.
  4. 4
    Swap in your dataReplace the DATA array with your own { name, value, color } items — slices, legend, and percentages all derive from it.
  5. 5
    Restyle itChange the colours, radius (R), or card styling; the arc math adapts to any radius automatically.
  6. 6
    Wire to an APIFetch your figures, map them to the DATA shape, and call render() to draw the live chart.

Real-world uses

Common Use Cases

Analytics traffic-source breakdowns
Show where visits come from on a dashboard — pair with a bar chart for trends over time.
Budget and spending composition
Visualise how a budget splits across categories alongside a donut chart for a hollow-centre variant.
Survey and poll results
Display answer distribution as shares of the whole, complementing a poll widget.
Portfolio and asset allocation
Show how holdings split across asset classes with live percentages.
Storage and quota usage
Break down disk or plan usage by type next to a quota usage meter.
Learning SVG arc drawing
A clear reference for arc-path math — compare with a gauge chart for a single-value arc.
Related: Skills Assessment Radar Chart
See the Skills Assessment Radar Chart for a related charts pattern worth pairing with this one.

Got questions?

Frequently Asked Questions

Each slice is an SVG <path> built from three commands: move to the centre, line to the slice's start point on the circle, then an elliptical arc (A) to its end point, then close (Z). The start/end points come from point(frac), which converts a fraction of the circle into x/y with Math.cos/Math.sin offset by −90° so the chart begins at twelve o'clock. The arc's large-arc-flag is set to 1 for any slice spanning more than half the circle.

A conic-gradient renders a pie as a single flat element with no per-slice interactivity — you can't hover, highlight, pull out, or animate an individual slice. Drawing each slice as its own <path> makes every slice a real DOM node you can attach tooltips and click handlers to, which is the entire value of an interactive chart. The arc math is the small cost of that interactivity.

Clicking a legend row flips a flag in the hidden map and calls render(), which recomputes the total from only the visible slices and redraws each remaining wedge proportioned to that new total. Because percentages and the running total both derive from the live sum, hiding one slice automatically re-proportions the rest — the same behaviour as professional charting libraries.

Edit the DATA array — each entry is { name, value, color }. Add, remove, or change entries and the slices, legend, total, and percentages all derive from it on the next render(). For real data, fetch your numbers, map them into that shape, and call render(); the arc math handles any number of slices and any values.

In React, hold the data and hidden state in useState and render the slices/legend from .map() with onClick toggles; in Vue, use v-for with ref state; in Angular, use *ngFor with component properties. The point()/slicePath() arc math is framework-agnostic — only the state and event wiring move into the framework, and the SVG paths render identically.