A read-only, CSS-only scatter plot. Each point is positioned by its
--x / --y (0–100). Color encodes a category
(pass / fail); points are circles, and --size would make bubbles.
The blue line is an optional trend line — here the data
shows a strong positive correlation between study hours and exam score.
No JavaScript.
| Hours | Score | Result |
|---|---|---|
| 1.0 | 30 | Fail |
| 2.0 | 42 | Fail |
| 2.5 | 38 | Fail |
| 3.0 | 55 | Fail |
| 4.0 | 58 | Fail |
| 4.5 | 65 | Pass |
| 5.0 | 62 | Pass |
| 5.5 | 70 | Pass |
| 6.0 | 75 | Pass |
| 7.0 | 80 | Pass |
| 8.0 | 88 | Pass |
| 9.5 | 95 | Pass |
<!-- .casca-plot frames the plot with axis bands; each tick sits at
--pos (0..100, percent of the axis). Each point is positioned by
--x / --y (0..100); --color encodes a category, --size makes bubbles. -->
<div class="casca-plot">
<span class="casca-axis-title" data-axis="y">Exam score</span>
<div class="casca-axis" data-axis="y">
<span class="casca-axis-tick" style="--pos: 0">0</span>
<span class="casca-axis-tick" style="--pos: 50">50</span>
<span class="casca-axis-tick" style="--pos: 100">100</span>
</div>
<div class="casca-scatter" aria-hidden="true" data-grid>
<!-- optional trend line: server-fit y at the left (--y1) and right (--y2) edge -->
<div class="casca-scatter-trend" style="--y1: 24; --y2: 96"></div>
<div class="casca-scatter-point"
style="--x: 30; --y: 55; --color: var(--casca-color-8)" title="3.0h → 55"></div>
<div class="casca-scatter-point"
style="--x: 70; --y: 80; --color: var(--casca-color-5)" title="7.0h → 80"></div>
<!-- ...one .casca-scatter-point per observation... -->
</div>
<div class="casca-axis" data-axis="x">
<span class="casca-axis-tick" style="--pos: 0">0h</span>
<span class="casca-axis-tick" style="--pos: 50">5h</span>
<span class="casca-axis-tick" style="--pos: 100">10h</span>
</div>
<span class="casca-axis-title" data-axis="x">Study hours</span>
</div>
The same plot with optional quadrant dividers
(--qx / --qy, 0–100) splitting it into four
cells for 2×2 analysis — here effort vs. impact. Corner labels are
plain positioned text. No JavaScript.
| Item | Effort | Impact | Quadrant |
|---|---|---|---|
| Search filters | 20 | 82 | Quick win |
| Dark mode | 34 | 68 | Quick win |
| New onboarding | 78 | 88 | Big bet |
| Billing rewrite | 72 | 60 | Big bet |
| Tooltip copy | 22 | 28 | Fill-in |
| Legacy migration | 85 | 24 | Money pit |
| Icon refresh | 62 | 38 | Money pit |
<!-- quadrant dividers split the plot at --qx / --qy (0..100); labels are
positioned by --x / --y like points -->
<div class="casca-scatter" aria-hidden="true">
<div class="casca-scatter-quadrants" style="--qx: 50; --qy: 50">
<span class="casca-scatter-quadrant-label" style="--x: 25; --y: 90">Quick wins</span>
<span class="casca-scatter-quadrant-label" style="--x: 75; --y: 90">Big bets</span>
<!-- ...one label per quadrant... -->
</div>
<div class="casca-scatter-point" style="--x: 20; --y: 82"></div>
<!-- ...points... -->
</div>
Color-code points by category to show clusters — here customer segments
by spend (x) vs. visit frequency (y). Each cluster gets a distinct
--color; a legend names them. No JavaScript.
| Spend | Frequency | Segment |
|---|---|---|
| 80 | 85 | Loyal |
| 88 | 78 | Loyal |
| 75 | 90 | Loyal |
| 92 | 82 | Loyal |
| 45 | 50 | Regular |
| 52 | 58 | Regular |
| 40 | 45 | Regular |
| 55 | 48 | Regular |
| 15 | 20 | New |
| 22 | 15 | New |
| 10 | 28 | New |
| 25 | 22 | New |
<!-- color-code points by category; a legend names the clusters -->
<div class="casca-scatter" aria-hidden="true" data-grid>
<div class="casca-scatter-point" style="--x: 80; --y: 85; --color: var(--casca-color-1)"></div>
<div class="casca-scatter-point" style="--x: 45; --y: 50; --color: var(--casca-color-5)"></div>
<div class="casca-scatter-point" style="--x: 15; --y: 20; --color: var(--casca-color-3)"></div>
<!-- ...one point per observation, --color per cluster... -->
</div>