Radar Chart HTML CSS JS — SVG Spider Chart

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

Share & Support

What's included

Features

Polar-to-Cartesian math: x = cx + r·sin(angle), y = cy − r·cos(angle) positions every point
Even axis spacing: N axes at 360/N degrees with the first axis at the top
Concentric ring grid: polygon gridlines that mirror the data shape, not plain circles
Two dataset overlays: translucent polygons on one grid for direct comparison
Stroke-dash animation: stroke-dasharray and dashoffset draw the outline on load
Draggable vertices: pointer events project the cursor back onto an axis to edit values
Live rebuild: dragging reruns the polar math to reshape the polygon in real time
SVG DOM nodes: each polygon, line, circle and label is stylable and event-bound
Vertex tooltips: native SVG title or labels reveal exact values
Resolution independent: crisp vector rendering at any size or zoom

About this UI Snippet

How to Build an SVG Radar Chart with Polar-to-Cartesian Math

Screenshot of the Radar Chart snippet rendered live

A radar chart — also called a spider or web chart — plots several metrics around a circle, with each axis radiating from the center and the data joined into a polygon. It is the go-to visualization for comparing multi-dimensional profiles like player stats, product scores or skill ratings. This implementation is built with inline SVG and a little trigonometry, supports two overlaid datasets, animates the fill on load, and lets you drag vertices to edit values live. No charting library is used. Here is the full breakdown.

Placing the axes with polar coordinates

The chart has N axes spread evenly around the center, one per metric, separated by 360 / N degrees. The core of the whole chart is the polar-to-Cartesian conversion. For a given axis index i and a radius r (how far out along that axis), the angle is i * (2*PI / N) measured from straight up, and the point is computed as:

x = cx + r * sin(angle) y = cy - r * cos(angle)

Using sin for x and -cos for y (with the minus because SVG's y-axis points down) places the first axis at the top and walks clockwise. A small helper function takes an axis index and a 0-to-1 value and returns the screen point, scaling the value by the chart's maximum radius. Every line, label and data vertex in the chart is positioned through this one function.

The concentric ring grid

The background grid is a set of concentric polygons rather than circles, so the gridlines mirror the data polygon's shape. For each ring level (say 20%, 40%, 60%, 80%, 100%) the code generates a points string by calling the polar helper for every axis at that fixed radius and joining the coordinates with spaces, then renders an SVG <polygon> with a faint stroke and no fill. Straight axis spokes are drawn as <line> elements from the center to each outermost vertex, and axis labels are positioned just beyond the outer ring, with their text-anchor adjusted based on which side of the chart they fall so labels never overlap the shape.

Building the data polygon

Each dataset is an array of values, one per axis, normalized to 0–1. The data polygon's points attribute is built exactly like a grid ring, but using each axis's actual data value as its radius instead of a fixed level. The resulting <polygon> is given a semi-transparent fill and a solid colored stroke. Small <circle> markers are drawn at each vertex so individual values are easy to read and grab.

Overlaying two datasets

Two datasets are rendered as two separate polygons with different colors and translucent fills layered on the same grid, making side-by-side comparison immediate — for example two players' attribute profiles. Because both use the same polar helper and coordinate system, they align perfectly. A legend maps each color to its label.

Animating the fill-in

On load the polygons animate in using SVG stroke techniques. The outline is drawn with a large stroke-dasharray set to the path length and an initial stroke-dashoffset equal to that length, which hides the stroke; transitioning the offset to zero makes the outline appear to draw itself around the shape. The fill opacity is simultaneously transitioned from zero, so the polygon both traces and fades in. This is the standard SVG line-drawing animation applied to a closed polygon.

Draggable vertices for live editing

The chart is interactive: each data vertex marker responds to pointer events. On press, the code records which dataset and axis the grabbed marker belongs to and sets a dragging reference. On move, it converts the pointer position back from Cartesian into a value along that axis — projecting the pointer's offset from center onto the axis direction and dividing by the max radius — clamps it to 0–1, updates the dataset, and rebuilds the polygon and markers. Releasing clears the drag. Because the rebuild reruns the same polar math, dragging a vertex smoothly reshapes the polygon in real time, effectively turning the chart into an input control. Both mouse and touch end events clear the drag state so it works on phones.

Tooltips and labels

Hovering or focusing a vertex can surface the exact value, implemented either through native SVG <title> elements for built-in tooltips or a positioned label. Axis labels and value rings give the chart context without clutter.

Why SVG over canvas here

SVG is ideal for a radar chart because each element — polygon, line, circle, label — is a real DOM node you can style with CSS, animate with transitions, and attach events to individually for dragging and tooltips. The whole chart is just trigonometry feeding coordinate strings into declarative SVG, which makes it crisp at any resolution, accessible, and easy to extend with more axes or datasets by changing the data arrays.

Build with AI

Build, Understand, Optimize, and Extend It With AI

You do not need to work through the trigonometry alone to understand this chart. Paste this snippet's HTML, CSS, and JS into an AI coding assistant like Claude and ask it to explain exactly why the pt() function uses sin for x and negative cos for y instead of the more common cos-for-x convention, and how that choice determines which axis sits at the top of the chart. The same assistant can help optimize it — ask whether rebuilding the entire svg.innerHTML on every build() call is necessary, or whether dragging a vertex could update just that one polygon's points attribute and its dot without touching the rings and axis labels at all. It's also useful for extending the chart: ask it to support a third overlaid dataset, snap dragged values to whole numbers with a visible readout, or add pinch-zoom for the radius on touch devices. 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 an SVG radar (spider) chart in plain HTML, CSS, and JavaScript using inline SVG created with createElementNS — no charting library, no canvas.

Requirements:
- Compute every point on the chart with one shared polar-to-Cartesian helper function that takes an axis index and a 0-100 value, converts the axis index to an angle assuming N evenly-spaced axes starting at the top (12 o'clock) and going clockwise, and returns an {x, y} pair scaled by a fixed maximum radius from a fixed center point.
- Draw a background grid of several concentric polygons (not circles) at fixed percentage levels (e.g. 20, 40, 60, 80, 100), each generated by calling the same polar helper for every axis at that fixed radius level and joining the results into an SVG polygon points string.
- Draw straight axis spoke lines from the center to each axis's outermost point, and axis text labels positioned just beyond the outer ring.
- Render at least two overlaid datasets as separate semi-transparent-fill, solid-stroke polygons sharing the same grid and polar helper, each with its own color, plus small circle markers at every data vertex.
- Animate each dataset polygon's outline drawing itself in on load using stroke-dasharray set to the polygon's total length and stroke-dashoffset animated from that same length down to zero via a CSS transition triggered on the next animation frame.
- Make every data vertex circle draggable with both mouse and touch events: on drag, convert the pointer position back into local chart coordinates, project it onto that vertex's axis direction to get a new 0-100 value, clamp it, update the underlying data array, and rebuild only that dataset's polygon points and the dragged vertex's own circle position, using the exact same polar helper function used for the initial render.

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
    View the profileSee each metric plotted on its own axis, joined into a polygon over the ring grid.
  2. 2
    Compare datasetsRead the two translucent overlays and legend to compare two profiles at a glance.
  3. 3
    Watch it animateOn load the polygon outline draws itself and the fill fades in via SVG stroke animation.
  4. 4
    Drag a vertexGrab any vertex marker and drag along its axis to change that value live.
  5. 5
    Read exact valuesHover or focus a vertex to surface its precise value through a tooltip.
  6. 6
    Edit the dataChange the dataset arrays or axis labels in the JS to chart your own metrics.

Real-world uses

Common Use Cases

Stats comparison
Compare player, product or candidate attributes across several metrics in a dashboard with tables.
Skill and competency maps
Visualize team or individual skill profiles for reviews and reporting.
Survey and scoring results
Plot multi-criteria survey averages or evaluation rubrics as an at-a-glance shape.
Interactive rating input
Use draggable vertices as a multi-axis input control for self-assessment forms.
Teaching trigonometry
Demonstrate polar coordinates and SVG geometry next to a color wheel picker.
RPG character sheets
Show strength, agility, intelligence and more as an editable spider chart.

Got questions?

Frequently Asked Questions

That places the first axis straight up and walks clockwise, which is the conventional radar layout. The minus on cos accounts for SVG y-coordinates increasing downward, so positive values go up the screen.

Concentric polygons share the same vertices as the data shape, so each ring is a scaled copy of the chart outline. This makes it easy to judge a value against the grid and looks cleaner than circular rings behind a polygon.

The pointer position is projected onto the grabbed axis direction and divided by the maximum radius to get a 0-to-1 value, which is clamped and written back to the dataset. The polygon is then rebuilt with the same polar math.

The polygon stroke uses stroke-dasharray equal to its length with an initial dashoffset that hides it. Transitioning the dashoffset to zero makes the outline trace itself, while the fill opacity fades in at the same time.

SVG elements are real DOM nodes, so each vertex can have its own event listeners for dragging and tooltips, be styled with CSS, and animated with transitions. It also stays crisp at any resolution without manual redrawing.

Yes. Use the JSX, Vue, Angular, or Tailwind export buttons on this page. In React, compute the polygon points from your data array with the same polar-coordinate math during render, and pass datasets as props — the SVG re-renders declaratively when values change.