v1.2.0
  1. ds
  2. Data display
  3. Heatmap

Heatmap

A week of cells on a sequential scale, with a legend and hover.

0003060912151821
Mon
Tue
Wed
Thu
Fri
Sat
Sun
Show code
<div class="heatmap" role="table" aria-label="Cron job starts per hour, Monday to Sunday">
  <div class="hm-r" role="row">
    <span role="columnheader"></span><span class="hm-col" role="columnheader">00</span> …
  </div>
  <div class="hm-r" role="row">
    <span class="hm-row" role="rowheader">Mon</span>
    <i class="hm-cell" role="cell" data-l="1" aria-label="1"></i> …
  </div>
  …
  <div class="hm-tip" hidden></div>
</div>
<div class="hm-legend" aria-hidden="true">
  <span>Less</span><i></i><i data-l="1"></i>…<i data-l="5"></i><span>More</span>
</div>

lab's cronmap: when 9 sample cron jobs start in a typical week, one cell per hour. Levels double: 0, 1, 2–3, 4–7, 8–15, 16+ starts. Hover a cell for the count. The grid is 24 columns of minmax(0, 1fr) with square cells and 2px gaps, so it fits a phone without scrolling.

The scale

Five steps of the accent hue, stepped in OKLCH lightness so each step looks as far from the next as the one before. Light mode runs light to dark and dark mode runs dark to light, so "more" always has the most contrast with the page. Empty cells are the ink at 7%, the same as fin1te.com's commit calendar. The lowest steps sit close to the surface on purpose: exact values live in the hover card and in a table.

--heat-1#d2cffa#38305c1.5 decorative1.5 decorative
--heat-2#aea6f0#5647902.2 decorative2.3 decorative
--heat-3#8b7ce3#7762c73.4 AA large3.8 AA large
--heat-4#6b52cc#9885f05.5 AA6.0 AA
--heat-5#4b2f9f#c0b6ff9.3 AAA9.9 AAA

API

ClassOnWhat it does
.heatmapdivThe grid. Set --cols (24). The first column holds the row heads.
.hm-rdivOptional row wrapper with display: contents, for table roles. Hovering a cell lights its row head.
.hm-col / .hm-rowspanColumn and row heads in mono. .on lights one.
.hm-celli, buttonA square cell. data-l from 0 to 5 picks the step.
.on.hm-cellThe ink ring that hover gives, for a selected cell.
.hm-legenddivLess, the six steps, More. Children are <i data-l>.
.hm-tipdivHover card inside the heatmap. Value in <b>, then a .label. Place it with left and top.
--heat-0 … --heat-5tokensEmpty, then the five steps, tuned per theme.

Accessibility

  • Say the takeaway in the aria-label. With role="table" on the grid and the roles above, a screen reader can also walk it cell by cell.
  • Colour is never the only channel: every count is in the hover card and each cell's label. Offer the same numbers as a table next to it.
  • If cells are buttons, use one tab stop for the grid and arrow keys inside it, not 168 tab stops.