v1.2.0
  1. ds
  2. Data display
  3. Waffle and treemap

Waffle and treemap

Shares as a grid of squares, or as nested boxes.

Two ways to show shares when there is no time axis. A waffle counts in whole percent, which people read faster than angles. A treemap shows a hierarchy, sized by value, and holds far more items than a donut.

Waffle

  • Standard46%
  • Infrequent access31%
  • Archive18%
  • Other5%

37%

of the error budget used,
11 days into the month

Show code
<div class="donut-row">
  <div class="waffle" role="img" aria-label="Lake storage by class: standard 46%, infrequent access 31%, archive 18%, other 5%"><i class="s1"></i><i class="s1"></i><i class="s1"></i><i class="s1"></i><i class="s1"></i><i class="s1"></i><i class="s1"></i><i class="s1"></i><i class="s1"></i><i class="s1"></i><i class="s1"></i><i class="s1"></i><i class="s1"></i><i class="s1"></i><i class="s1"></i><i class="s1"></i><i class="s1"></i><i class="s1"></i><i class="s1"></i><i class="s1"></i><i class="s1"></i><i class="s1"></i><i class="s1"></i><i class="s1"></i><i class="s1"></i><i class="s1"></i><i class="s1"></i><i class="s1"></i><i class="s1"></i><i class="s1"></i><i class="s1"></i><i class="s1"></i><i class="s1"></i><i class="s1"></i><i class="s1"></i><i class="s1"></i><i class="s1"></i><i class="s1"></i><i class="s1"></i><i class="s1"></i><i class="s1"></i><i class="s1"></i><i class="s1"></i><i class="s1"></i><i class="s1"></i><i class="s1"></i><i class="s2"></i><i class="s2"></i><i class="s2"></i><i class="s2"></i><i class="s2"></i><i class="s2"></i><i class="s2"></i><i class="s2"></i><i class="s2"></i><i class="s2"></i><i class="s2"></i><i class="s2"></i><i class="s2"></i><i class="s2"></i><i class="s2"></i><i class="s2"></i><i class="s2"></i><i class="s2"></i><i class="s2"></i><i class="s2"></i><i class="s2"></i><i class="s2"></i><i class="s2"></i><i class="s2"></i><i class="s2"></i><i class="s2"></i><i class="s2"></i><i class="s2"></i><i class="s2"></i><i class="s2"></i><i class="s2"></i><i class="s3"></i><i class="s3"></i><i class="s3"></i><i class="s3"></i><i class="s3"></i><i class="s3"></i><i class="s3"></i><i class="s3"></i><i class="s3"></i><i class="s3"></i><i class="s3"></i><i class="s3"></i><i class="s3"></i><i class="s3"></i><i class="s3"></i><i class="s3"></i><i class="s3"></i><i class="s3"></i><i class="s6"></i><i class="s6"></i><i class="s6"></i><i class="s6"></i><i class="s6"></i></div>
  <ul class="ch-legend col">
    <li class="s1"><span>Standard</span><b>46%</b></li>
    <li class="s2"><span>Infrequent access</span><b>31%</b></li>
    <li class="s3"><span>Archive</span><b>18%</b></li>
    <li class="s6"><span>Other</span><b>5%</b></li>
  </ul>
</div>
<div class="donut-row">
  <div class="waffle" style="--size:7rem" role="img" aria-label="37% of the monthly error budget used"><i class="c-down"></i><i class="c-down"></i><i class="c-down"></i><i class="c-down"></i><i class="c-down"></i><i class="c-down"></i><i class="c-down"></i><i class="c-down"></i><i class="c-down"></i><i class="c-down"></i><i class="c-down"></i><i class="c-down"></i><i class="c-down"></i><i class="c-down"></i><i class="c-down"></i><i class="c-down"></i><i class="c-down"></i><i class="c-down"></i><i class="c-down"></i><i class="c-down"></i><i class="c-down"></i><i class="c-down"></i><i class="c-down"></i><i class="c-down"></i><i class="c-down"></i><i class="c-down"></i><i class="c-down"></i><i class="c-down"></i><i class="c-down"></i><i class="c-down"></i><i class="c-down"></i><i class="c-down"></i><i class="c-down"></i><i class="c-down"></i><i class="c-down"></i><i class="c-down"></i><i class="c-down"></i><i class="rest"></i><i class="rest"></i><i class="rest"></i><i class="rest"></i><i class="rest"></i><i class="rest"></i><i class="rest"></i><i class="rest"></i><i class="rest"></i><i class="rest"></i><i class="rest"></i><i class="rest"></i><i class="rest"></i><i class="rest"></i><i class="rest"></i><i class="rest"></i><i class="rest"></i><i class="rest"></i><i class="rest"></i><i class="rest"></i><i class="rest"></i><i class="rest"></i><i class="rest"></i><i class="rest"></i><i class="rest"></i><i class="rest"></i><i class="rest"></i><i class="rest"></i><i class="rest"></i><i class="rest"></i><i class="rest"></i><i class="rest"></i><i class="rest"></i><i class="rest"></i><i class="rest"></i><i class="rest"></i><i class="rest"></i><i class="rest"></i><i class="rest"></i><i class="rest"></i><i class="rest"></i><i class="rest"></i><i class="rest"></i><i class="rest"></i><i class="rest"></i><i class="rest"></i><i class="rest"></i><i class="rest"></i><i class="rest"></i><i class="rest"></i><i class="rest"></i><i class="rest"></i><i class="rest"></i><i class="rest"></i><i class="rest"></i><i class="rest"></i><i class="rest"></i><i class="rest"></i><i class="rest"></i><i class="rest"></i><i class="rest"></i><i class="rest"></i><i class="rest"></i></div>
  <div><p class="ch-v">37%</p><p class="ch-sub">of the error budget used,<br>11 days into the month</p></div>
</div>

One hundred squares in reading order, one per percent. Round so the counts add up to 100. With one category against empty squares it becomes a budget: you can count what is left.

Treemap

Spend by service

$10.6k in September

  • Compute
  • Storage
  • Databases
  • Network
Show code
<figure class="chart boxed">
  <figcaption class="ch-head">
    <div><p class="ch-title">Spend by service</p><p class="ch-sub">$10.6k in September</p></div>
    <ul class="ch-legend"><li class="s1">Compute</li><li class="s2">Storage</li><li class="s3">Databases</li><li class="s4">Network</li></ul>
  </figcaption>
  <div class="treemap" role="img" aria-label="Cloud spend by service, $10.6k this month. EKS nodes is the largest at $4.1k.">
  <div class="tm col s1" style="--v:7020">
    <div class="tm-t" style="--v:4100" title="EKS nodes: $4.1k"><b>EKS nodes</b><span>$4.1k</span></div>
    <div class="tm-t" style="--v:2300" title="EC2: $2.3k"><b>EC2</b><span>$2.3k</span></div>
    <div class="tm-t" style="--v:620" title="Lambda: $0.6k"><b>Lambda</b><span>$0.6k</span></div>
  </div>
  <div class="tm col s2" style="--v:1440">
    <div class="tm-t" style="--v:1100" title="S3: $1.1k"><b>S3</b><span>$1.1k</span></div>
    <div class="tm-t sm" style="--v:340" title="EBS: $0.3k"><b>EBS</b><span>$0.3k</span></div>
  </div>
  <div class="tm col s3" style="--v:960">
    <div class="tm-t" style="--v:760" title="RDS Postgres: $0.8k"><b>RDS Postgres</b><span>$0.8k</span></div>
    <div class="tm-t sm" style="--v:200" title="ElastiCache: $0.2k"><b>ElastiCache</b><span>$0.2k</span></div>
  </div>
  <div class="tm col s4" style="--v:1210">
    <div class="tm-t" style="--v:680" title="NAT gateway: $0.7k"><b>NAT gateway</b><span>$0.7k</span></div>
    <div class="tm-t" style="--v:530" title="Data transfer: $0.5k"><b>Data transfer</b><span>$0.5k</span></div>
  </div>
</div>
</figure>

Slice and dice with flexbox: the top level splits across, each group splits down, and every tile grows by its --v. No layout code runs; the browser does the arithmetic. Tiles too small for a label get .sm and keep a title. For deep hierarchies use a squarified layout from a library and position tiles absolutely; the tile styles stay the same.

ClassOnWhat it does
.waffledivA grid of --cols (10) squares, --size wide (10rem). Each <i> takes a series or status class; .rest for the remainder.
.treemapdivThe frame, --h tall (16rem). Its children split across.
.tmdivA group that grows by --v. .col splits its children down. Set the series class here so tiles inherit it.
.tm-tdivA tile: name in b, value in span, grows by --v. .sm hides the text.
Do
  • Colour a treemap by the top level only.
  • Values on tiles, totals in the head.
Don't
  • Treemaps for values that can be negative.
  • Waffles with more than five categories.

Accessibility

  • Both are one image with the shares in the label. Give the same numbers as a table or legend.