Heatmap
Configurable N×M grid for risk matrices, priority grids, skill assessments, and any two-axis categorical visualization. Pure CSS, zero JavaScript required. Optionally enhance with keyboard navigation and selection.
Example
Rare
Unlikely
Possible
Likely
Certain
Major
3
6
9
12
15
Moderate
2
4
6
8
10
Minor
1
2
3
4
5
<div class="omni-heatmap" role="grid" aria-label="Risk Matrix" data-columns="5" data-rows="3">
<div class="omni-heatmap-header" role="row">
<div class="omni-heatmap-corner" role="columnheader"></div>
<div class="omni-heatmap-col-header" role="columnheader">Rare</div>
<!-- ... more columns ... -->
</div>
<div class="omni-heatmap-row" role="row">
<div class="omni-heatmap-row-header" role="rowheader">Major</div>
<div class="omni-heatmap-cell" role="gridcell" data-level="critical">15</div>
<!-- ... more cells ... -->
</div>
</div>
Use Cases
Risk Matrix (5×5)
Standard likelihood × impact assessment:
Impact →
Likelihood ↓
Likelihood ↓
Rare
Unlikely
Possible
Likely
Certain
Catastrophic
5
10
15
20
25
Major
4
8
12
16
20
Moderate
3
6
9
12
15
Minor
2
4
6
8
10
Negligible
1
2
3
4
5
Priority Matrix (3×3)
Simple effort vs. value prioritization:
Low Effort
Medium Effort
High Effort
High Value
Do Now
Plan
Consider
Medium Value
Quick Win
Balance
Defer
Low Value
Easy Fill
Avoid
Drop
Severity Levels
Use data-level to convey meaning through color:
Critical
High
Medium
Low
Info
Levels
Critical
High
Medium
Low
Info
<div class="omni-heatmap-cell" data-level="critical">Critical</div>
<div class="omni-heatmap-cell" data-level="high">High</div>
<div class="omni-heatmap-cell" data-level="medium">Medium</div>
<div class="omni-heatmap-cell" data-level="low">Low</div>
<div class="omni-heatmap-cell" data-level="info">Info</div>
Pattern Overlays (Colorblind Accessibility)
Add data-pattern to provide texture overlays that don't rely on color alone:
Diagonal
Dots
Crosshatch
Horizontal
Patterns
Critical
High
Medium
Low
<div class="omni-heatmap-cell" data-level="critical" data-pattern="diagonal">Critical</div>
<div class="omni-heatmap-cell" data-level="high" data-pattern="dots">High</div>
<div class="omni-heatmap-cell" data-level="medium" data-pattern="crosshatch">Medium</div>
<div class="omni-heatmap-cell" data-level="low" data-pattern="horizontal">Low</div>
Interactive Mode
Add data-interactive to enable hover states. Use data-selected to highlight cells:
Q1
Q2
Q3
Q4
Product A
95
78
92
85
Product B
62
71
68
74
Product C
45
52
58
63
Hover over cells to see the highlight effect. The cell showing "92" has data-selected.
<div class="omni-heatmap" data-interactive>
<!-- ... -->
<div class="omni-heatmap-cell" data-level="critical" data-selected tabindex="0">92</div>
</div>
Grid Sizes
Supports 3×3 to 6×6 grids via data-columns and data-rows:
3×3 Grid
A
B
C
1
9
6
3
2
6
4
2
3
3
2
1
4×4 Grid
A
B
C
D
1
16
12
8
4
2
12
9
6
3
3
8
6
4
2
4
4
3
2
1
<div class="omni-heatmap" data-columns="3" data-rows="3">...</div>
<div class="omni-heatmap" data-columns="4" data-rows="4">...</div>
<div class="omni-heatmap" data-columns="5" data-rows="5">...</div>
<div class="omni-heatmap" data-columns="6" data-rows="6">...</div>
Legend
Optional legend component for explaining severity levels:
Critical (15-25)
High (8-14)
Medium (4-7)
Low (2-3)
Info (1)
<div class="omni-heatmap-legend">
<div class="omni-heatmap-legend-item">
<div class="omni-heatmap-legend-swatch" data-level="critical"></div>
<span>Critical (15-25)</span>
</div>
<!-- ... more items ... -->
</div>
API Reference
Classes
| Class | Description |
|---|---|
.omni-heatmap |
Container for the grid |
.omni-heatmap-header |
Header row containing column headers |
.omni-heatmap-corner |
Top-left corner cell (optional label) |
.omni-heatmap-col-header |
Column header cell |
.omni-heatmap-row |
Data row containing row header and cells |
.omni-heatmap-row-header |
Row header cell |
.omni-heatmap-cell |
Data cell |
.omni-heatmap-legend |
Legend container (optional) |
.omni-heatmap-legend-item |
Legend item |
.omni-heatmap-legend-swatch |
Legend color swatch |
Data Attributes
| Attribute | Values | Default | Description |
|---|---|---|---|
data-columns |
3, 4, 5, 6 | 5 | Number of data columns |
data-rows |
3, 4, 5, 6 | 5 | Number of data rows |
data-level |
critical, high, medium, low, info | — | Cell severity/importance level |
data-pattern |
diagonal, dots, crosshatch, horizontal | — | Colorblind-accessible pattern overlay |
data-selected |
(presence) | — | Highlights cell as selected |
data-interactive |
(presence) | — | Enables hover states on cells |
CSS Custom Properties
| Property | Default | Description |
|---|---|---|
--omni-heatmap-columns |
5 | Number of columns (override with inline style for custom sizes) |
--omni-heatmap-rows |
5 | Number of rows (override with inline style for custom sizes) |
--omni-heatmap-cell-size |
minmax(3rem, 1fr) | Cell width/height |
--omni-heatmap-gap |
2px | Gap between cells |
--omni-heatmap-header-width |
auto | Row header width (adjust for long labels) |
Accessibility
- Uses ARIA grid pattern with
role="grid",role="row",role="gridcell",role="columnheader", androle="rowheader" - Multi-encoding strategy: color + numeric values + optional patterns ensures information isn't color-dependent
- Four pattern types (diagonal, dots, crosshatch, horizontal) provide additional visual differentiation for colorblind users
- Add
tabindex="0"to cells for keyboard navigation support - Focus visible indicators with semantic color-matched outlines
- All color levels meet WCAG minimum 3:1 contrast requirements
- Works in light, dark, and high-contrast color modes
- Respects
prefers-reduced-motionfor transitions - Responsive design with horizontal scrolling on small screens
- Always include descriptive
aria-labelon the grid container