No SVG. No canvas. No JS charting library.
st-core.fscss v2 now draws spider (radar) charts the same way it draws area and line charts: FSCSS arrays, CSS custom properties, and clip-path: polygon(). The result looks like a modern product dashboard — skills matrices, multi-axis scores, team comparisons — and the payload stays tiny.
The module Source:
github.com/fscss-ttr/st-core.fscss
Why this feels modern
Modern UI is not “more libraries.” It’s clarity, density, and motion that doesn’t cost a framework.
Spider charts in st-core lean on:
-
Token-driven color —
--st-accent,--st-surface,--st-border. Change one variable; the whole chart follows. -
Soft polar geometry — fill via
color-mix, stroke as a dual-pass polygon, rings and spokes as gradients. No harsh SVG strokes fighting your theme. - Composable layers — grid, spokes, fill, line, dots stack as plain divs. Multi-series is just more layers with their own accent.
- Native inheritance — coordinates are custom properties. Children inherit. Multi-team cards don’t need a state tree; they need scoped hosts.
That combination reads as “product UI,” not “demo from 2014.”
Why st-core stays lightweight
| What you don’t ship | What you do ship |
|---|---|
| Chart.js / D3 / Recharts | A few @define mixins |
| SVG path builders | clip-path: polygon() |
| Canvas + DPR logic | CSS % + sin() / cos() in calc()
|
| Hydration for the chart | Optional JS that only sets variables |
Geometry is decided at compile time from @arr length. Runtime work is rewriting --st-sxN / --st-syN (or --st-pN for linear charts). Animations can use transition: clip-path on the compositor.
Compiled CSS for a chart class stays on the order of about a kilobyte, not a hundred. The page paints charts with zero chart-library JavaScript.
That’s the st-core bet: visualization as styling, not as an app runtime.
The one rule (same as linear charts)
Points write. Renderers read.
@st-spider-points(array) → writes --st-sxN / --st-syN on the host
@st-spider-fill / line / dots → only read those variables
Call points on the host that owns the series. Multi-series means one host per series — same pattern as multi-line area charts in v2.
Angle 0° is at the top. Values are 0–100 scores scaled by rmax (default 42% of the box).
What you can build
1. Minimal radar
Six axes, one series, grid + spokes + fill + line + dots.
@import((*) from st-core@v2)
@st-root()
@st-spider-root()
@arr skills[80, 65, 90, 55, 70, 85]
@st-spider-fill(.spider-fill, skills)
@st-spider-line(.spider-line, skills)
@st-spider-dots(.spider-dot-, skills, 9px)
@st-spider-grid(.spider-grid)
@st-spider-spokes(.spider-spokes, skills)
.spider {
@st-spider-points(skills, 42)
position: relative;
width: 280px;
height: 280px;
border-radius: 50%;
background: var(--st-surface);
}
<div class="spider">
<div class="spider-grid"></div>
<div class="spider-spokes"></div>
<div class="spider-fill"></div>
<div class="spider-line"></div>
<div class="spider-dot-1"></div>
<!-- … through .spider-dot-6 -->
</div>
Dots need real DOM nodes — the mixin only generates the CSS.
2. Team comparison cards
Two hosts, two accents, shared label layout:
@arr teamA[92, 78, 85, 55, 48, 80]
@arr teamB[68, 82, 70, 95, 62, 58]
.spider-wrap.team-a {
@st-spider-points(teamA, 42)
--st-accent: #9d7eff;
--st-spider-fill-opacity: 28%;
}
.spider-wrap.team-b {
@st-spider-points(teamB, 42)
--st-accent: #4fffb0;
--st-spider-fill-opacity: 30%;
}
Axis labels are ordinary absolute spans (Speed, Quality, UX, Scale, Cost, Support,...) around the circle. No special chart API — just layout.
3. Multi-series overlay
One polar grid, five polygons, each series a full-size absolute layer with its own @st-spider-points and --st-accent. Lower --st-spider-fill-opacity keeps overlaps readable.
4. Live updates without a library
function polarVars(values, rmax = 42) {
const n = values.length;
return values.map((v, i) => {
const ang = (i * 360) / n;
const r = (v / 100) * rmax;
return (
`--st-sx${i + 1}: calc(50% + (${r} * 1%) * sin(${ang} * 1deg));` +
`--st-sy${i + 1}: calc(50% - (${r} * 1%) * cos(${ang} * 1deg));`
);
}).join(" ");
}
host.style.cssText = polarVars([80, 65, 90, 55, 70, 85]);
Same length as the compiled polygon; values morph. Optional transition on clip-path for soft motion.
Under the hood (short)
| Layer | Technique |
|---|---|
| Coordinates |
--st-sxN / --st-syN from sin / cos in calc()
|
| Fill | Closed polygon() + color-mix with --st-spider-fill-opacity
|
| Stroke | Dual-pass polygon; inner path scaled by --st-spider-stroke-scale
|
| Rings |
radial-gradient stops at 20 / 40 / 60 / 80% |
| Spokes | Thin conic-gradient bands from -90deg + center mask |
Everything is documented in the repo: README (API + examples), EXPLAINED (every @define), integration/html (dual-team and multi-series demos).
Install
NPM CLI:
npm install -g fscss
charts.fscss charts.css
Testing via CDN:
<script src="https://cdn.jsdelivr.net/npm/fscss@1.2.5/runtime.min.js" async></script>
@import((*) from st-core@v2)
Prefer FSCSS CLI for production CSS with zero runtime preprocessor.
Requires FSCSS v1.2.3+. MIT licensed.
Area and line charts proved that dashboards don’t need a JS chart runtime. Spider charts extend that idea into polar space without changing the contract: arrays in, custom properties out, polygons on screen.
Explore the module, the demos, and the under-the-hood write-up here:
github.com/fscss-ttr/st-core.fscss
Pure CSS. Still lightweight. Now with radar.
Top comments (1)
tr.ee/dev-to