Open demo

CSS code

HTML
<div class="heat">
  <h2>1,284 commits in the last year</h2>
  <p class="sub">Longest streak 34 days · Busiest day 12 March</p>
  <div class="scroll" tabindex="0" role="region" aria-label="Activity heatmap, scrolls sideways">
    <div class="months" aria-hidden="true"><span>Sep</span><span>Oct</span><span>Nov</span><span>Dec</span><span>Jan</span><span>Feb</span><span>Mar</span><span>Apr</span><span>May</span><span>Jun</span><span>Jul</span><span>Aug</span></div>
    <div class="body">
      <div class="dows" aria-hidden="true"><span></span><span>M</span><span></span><span>W</span><span></span><span>F</span><span></span></div>
      <div class="cells" role="img" aria-label="Daily commits for the last 52 weeks, shaded in five levels from none to most. Monthly totals are in the table that follows.">
      <i class="l0"></i><i class="l1"></i><i class="l2"></i><i class="l3"></i><i class="l4"></i><i class="l0"></i><i class="l1"></i>
      <i class="l2"></i><i class="l3"></i><i class="l4"></i><i class="l0"></i><i class="l1"></i><i class="l0"></i><i class="l3"></i>
      <i class="l4"></i><i class="l0"></i><i class="l1"></i><i class="l0"></i><i class="l3"></i><i class="l4"></i><i class="l0"></i>
      <i class="l1"></i><i class="l0"></i><i class="l3"></i><i class="l4"></i><i class="l0"></i><i class="l1"></i><i class="l2"></i>
      <i class="l3"></i><i class="l4"></i><i class="l0"></i><i class="l1"></i><i class="l2"></i><i class="l3"></i><i class="l0"></i>
      <i class="l0"></i><i class="l1"></i><i class="l2"></i><i class="l3"></i><i class="l0"></i><i class="l0"></i><i class="l1"></i>
      <i class="l2"></i><i class="l3"></i><i class="l0"></i><i class="l0"></i><i class="l1"></i><i class="l2"></i><i class="l3"></i>
      <i class="l0"></i><i class="l0"></i><i class="l1"></i><i class="l2"></i><i class="l3"></i><i class="l4"></i><i class="l0"></i>
      <i class="l1"></i><i class="l2"></i><i class="l3"></i><i class="l4"></i><i class="l0"></i><i class="l0"></i><i class="l2"></i>
      <i class="l3"></i><i class="l4"></i><i class="l0"></i><i class="l0"></i><i class="l2"></i><i class="l3"></i><i class="l4"></i>
      <i class="l0"></i><i class="l0"></i><i class="l2"></i><i class="l3"></i><i class="l4"></i><i class="l0"></i><i class="l1"></i>
      <i class="l2"></i><i class="l3"></i><i class="l4"></i><i class="l0"></i><i class="l1"></i><i class="l2"></i><i class="l0"></i>
      <i class="l4"></i><i class="l0"></i><i class="l1"></i><i class="l2"></i><i class="l0"></i><i class="l4"></i><i class="l0"></i>
      <i class="l1"></i><i class="l2"></i><i class="l0"></i><i class="l4"></i><i class="l0"></i><i class="l1"></i><i class="l2"></i>
      <i class="l0"></i><i class="l4"></i><i class="l0"></i><i class="l1"></i><i class="l2"></i><i class="l3"></i><i class="l4"></i>
      <i class="l0"></i><i class="l1"></i><i class="l2"></i><i class="l3"></i><i class="l4"></i><i class="l0"></i><i class="l1"></i>
      <i class="l2"></i><i class="l3"></i><i class="l4"></i><i class="l0"></i><i class="l1"></i><i class="l2"></i><i class="l3"></i>
      <i class="l4"></i><i class="l0"></i><i class="l1"></i><i class="l2"></i><i class="l3"></i><i class="l4"></i><i class="l0"></i>
      <i class="l1"></i><i class="l2"></i><i class="l3"></i><i class="l4"></i><i class="l0"></i><i class="l1"></i><i class="l0"></i>
      <i class="l3"></i><i class="l4"></i><i class="l0"></i><i class="l1"></i><i class="l0"></i><i class="l3"></i><i class="l4"></i>
      <i class="l0"></i><i class="l1"></i><i class="l0"></i><i class="l3"></i><i class="l4"></i><i class="l0"></i><i class="l1"></i>
      <i class="l0"></i><i class="l3"></i><i class="l4"></i><i class="l0"></i><i class="l1"></i><i class="l2"></i><i class="l3"></i>
      <i class="l4"></i><i class="l0"></i><i class="l1"></i><i class="l2"></i><i class="l3"></i><i class="l0"></i><i class="l0"></i>
      <i class="l1"></i><i class="l2"></i><i class="l3"></i><i class="l0"></i><i class="l0"></i><i class="l1"></i><i class="l2"></i>
      <i class="l3"></i><i class="l0"></i><i class="l0"></i><i class="l1"></i><i class="l2"></i><i class="l3"></i><i class="l4"></i>
      <i class="l0"></i><i class="l1"></i><i class="l2"></i><i class="l3"></i><i class="l4"></i><i class="l0"></i><i class="l0"></i>
      <i class="l2"></i><i class="l3"></i><i class="l4"></i><i class="l0"></i><i class="l0"></i><i class="l2"></i><i class="l3"></i>
      <i class="l4"></i><i class="l0"></i><i class="l0"></i><i class="l2"></i><i class="l3"></i><i class="l4"></i><i class="l0"></i>
      <i class="l0"></i><i class="l2"></i><i class="l3"></i><i class="l4"></i><i class="l0"></i><i class="l1"></i><i class="l2"></i>
      <i class="l3"></i><i class="l4"></i><i class="l0"></i><i class="l1"></i><i class="l2"></i><i class="l0"></i><i class="l4"></i>
      <i class="l0"></i><i class="l1"></i><i class="l2"></i><i class="l0"></i><i class="l4"></i><i class="l0"></i><i class="l1"></i>
      <i class="l2"></i><i class="l0"></i><i class="l4"></i><i class="l0"></i><i class="l1"></i><i class="l2"></i><i class="l3"></i>
      <i class="l4"></i><i class="l0"></i><i class="l1"></i><i class="l2"></i><i class="l3"></i><i class="l4"></i><i class="l0"></i>
      <i class="l1"></i><i class="l2"></i><i class="l3"></i><i class="l4"></i><i class="l0"></i><i class="l1"></i><i class="l2"></i>
      <i class="l3"></i><i class="l4"></i><i class="l0"></i><i class="l1"></i><i class="l2"></i><i class="l3"></i><i class="l4"></i>
      <i class="l0"></i><i class="l1"></i><i class="l2"></i><i class="l3"></i><i class="l4"></i><i class="l0"></i><i class="l1"></i>
      <i class="l2"></i><i class="l3"></i><i class="l4"></i><i class="l0"></i><i class="l1"></i><i class="l0"></i><i class="l3"></i>
      <i class="l4"></i><i class="l0"></i><i class="l1"></i><i class="l0"></i><i class="l3"></i><i class="l4"></i><i class="l0"></i>
      <i class="l1"></i><i class="l0"></i><i class="l3"></i><i class="l4"></i><i class="l0"></i><i class="l1"></i><i class="l2"></i>
      <i class="l3"></i><i class="l4"></i><i class="l0"></i><i class="l1"></i><i class="l2"></i><i class="l3"></i><i class="l0"></i>
      <i class="l0"></i><i class="l1"></i><i class="l2"></i><i class="l3"></i><i class="l0"></i><i class="l0"></i><i class="l1"></i>
      <i class="l2"></i><i class="l3"></i><i class="l0"></i><i class="l0"></i><i class="l1"></i><i class="l2"></i><i class="l3"></i>
      <i class="l0"></i><i class="l0"></i><i class="l1"></i><i class="l2"></i><i class="l3"></i><i class="l4"></i><i class="l0"></i>
      <i class="l1"></i><i class="l2"></i><i class="l3"></i><i class="l4"></i><i class="l0"></i><i class="l0"></i><i class="l2"></i>
      <i class="l3"></i><i class="l4"></i><i class="l0"></i><i class="l0"></i><i class="l2"></i><i class="l3"></i><i class="l4"></i>
      <i class="l0"></i><i class="l0"></i><i class="l2"></i><i class="l3"></i><i class="l4"></i><i class="l0"></i><i class="l1"></i>
      <i class="l2"></i><i class="l3"></i><i class="l4"></i><i class="l0"></i><i class="l1"></i><i class="l2"></i><i class="l0"></i>
      <i class="l4"></i><i class="l0"></i><i class="l1"></i><i class="l2"></i><i class="l0"></i><i class="l4"></i><i class="l0"></i>
      <i class="l1"></i><i class="l2"></i><i class="l0"></i><i class="l4"></i><i class="l0"></i><i class="l1"></i><i class="l2"></i>
      <i class="l0"></i><i class="l4"></i><i class="l0"></i><i class="l1"></i><i class="l2"></i><i class="l3"></i><i class="l4"></i>
      <i class="l0"></i><i class="l1"></i><i class="l2"></i><i class="l3"></i><i class="l4"></i><i class="l0"></i><i class="l1"></i>
      <i class="l2"></i><i class="l3"></i><i class="l4"></i><i class="l0"></i><i class="l1"></i><i class="l2"></i><i class="l3"></i>
      </div>
    </div>
  </div>
  <p class="legend"><span>Less</span><span aria-hidden="true" style="display:contents"><i class="l0"></i><i class="l1"></i><i class="l2"></i><i class="l3"></i><i class="l4"></i></span><span>More</span></p>
  <div class="sr-only"><table>
    <caption>Commits per month, September 2025 to August 2026</caption>
    <thead><tr><th scope="col">Month</th><th scope="col">Commits</th></tr></thead>
    <tbody>
      <tr><th scope="row">September 2025</th><td>96</td></tr>
      <tr><th scope="row">October 2025</th><td>112</td></tr>
      <tr><th scope="row">November 2025</th><td>88</td></tr>
      <tr><th scope="row">December 2025</th><td>64</td></tr>
      <tr><th scope="row">January 2026</th><td>101</td></tr>
      <tr><th scope="row">February 2026</th><td>118</td></tr>
      <tr><th scope="row">March 2026</th><td>142</td></tr>
      <tr><th scope="row">April 2026</th><td>127</td></tr>
      <tr><th scope="row">May 2026</th><td>109</td></tr>
      <tr><th scope="row">June 2026</th><td>115</td></tr>
      <tr><th scope="row">July 2026</th><td>98</td></tr>
      <tr><th scope="row">August 2026</th><td>114</td></tr>
    </tbody>
  </table></div>
</div>
CSS
/* Activity heatmap: 52 week columns of 7 day cells. The cells are one image to assistive tech;
   a visually hidden table carries the same data as text. */
.heat{--hm-0:#eaeef3;--hm-1:#c9e3d0;--hm-2:#86c99b;--hm-3:#41a862;--hm-4:#1e7a41;--hm-muted:#5f6b7c;
  box-sizing:border-box;width:100%;max-width:840px;padding:22px 24px 20px;background:#fff;border-radius:16px;
  box-shadow:0 14px 34px -18px rgba(18,24,40,.25)}
.heat h2{font-size:.95rem;margin:0 0 3px}
.heat .sub{font-size:.79rem;color:var(--hm-muted);margin:0 0 16px}
.heat .scroll{overflow-x:auto;padding:2px;border-radius:6px}
.heat .scroll:focus-visible{outline:2px solid #6d28d9;outline-offset:2px}
.heat .months{display:grid;grid-auto-flow:column;grid-auto-columns:1fr;font-size:.66rem;color:var(--hm-muted);
  font-weight:700;margin-bottom:5px;min-width:700px;padding-left:26px}
.heat .body{display:flex;gap:6px;min-width:700px}
.heat .dows{display:grid;grid-template-rows:repeat(7,1fr);gap:3px;font-size:.6rem;color:var(--hm-muted);font-weight:700;width:20px;align-items:center}
.heat .cells{display:grid;grid-template-rows:repeat(7,1fr);grid-auto-flow:column;grid-auto-columns:1fr;gap:3px;flex:1}
.heat .cells i,.heat .legend i{border-radius:2.5px;font-style:normal}
.heat .cells i{aspect-ratio:1;min-height:9px}
.heat .l0{background:var(--hm-0)}.heat .l1{background:var(--hm-1)}.heat .l2{background:var(--hm-2)}.heat .l3{background:var(--hm-3)}.heat .l4{background:var(--hm-4)}
.heat .legend{display:flex;align-items:center;gap:6px;justify-content:flex-end;margin:14px 0 0;font-size:.72rem;color:var(--hm-muted)}
.heat .legend i{width:11px;height:11px}
.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}

Bootstrap 5 code

Requires: Bootstrap 5.3.8 CSS

HTML
<div class="heat card w-100">
  <h2 class="fw-bold mb-1" style="font-size:.95rem">1,284 commits in the last year</h2>
  <p class="text-muted-hm mb-3" style="font-size:.79rem">Longest streak 34 days · Busiest day 12 March</p>
  <div class="scroll overflow-x-auto" tabindex="0" role="region" aria-label="Activity heatmap, scrolls sideways">
    <div class="months text-muted-hm fw-bold mb-1" aria-hidden="true"><span>Sep</span><span>Oct</span><span>Nov</span><span>Dec</span><span>Jan</span><span>Feb</span><span>Mar</span><span>Apr</span><span>May</span><span>Jun</span><span>Jul</span><span>Aug</span></div>
    <div class="wk d-flex gap-2">
      <div class="dows text-muted-hm fw-bold flex-shrink-0" aria-hidden="true"><span></span><span>M</span><span></span><span>W</span><span></span><span>F</span><span></span></div>
      <div class="cells flex-grow-1" role="img" aria-label="Daily commits for the last 52 weeks, shaded in five levels from none to most. Monthly totals are in the table that follows.">
      <i class="l0"></i><i class="l1"></i><i class="l2"></i><i class="l3"></i><i class="l4"></i><i class="l0"></i><i class="l1"></i>
      <i class="l2"></i><i class="l3"></i><i class="l4"></i><i class="l0"></i><i class="l1"></i><i class="l0"></i><i class="l3"></i>
      <i class="l4"></i><i class="l0"></i><i class="l1"></i><i class="l0"></i><i class="l3"></i><i class="l4"></i><i class="l0"></i>
      <i class="l1"></i><i class="l0"></i><i class="l3"></i><i class="l4"></i><i class="l0"></i><i class="l1"></i><i class="l2"></i>
      <i class="l3"></i><i class="l4"></i><i class="l0"></i><i class="l1"></i><i class="l2"></i><i class="l3"></i><i class="l0"></i>
      <i class="l0"></i><i class="l1"></i><i class="l2"></i><i class="l3"></i><i class="l0"></i><i class="l0"></i><i class="l1"></i>
      <i class="l2"></i><i class="l3"></i><i class="l0"></i><i class="l0"></i><i class="l1"></i><i class="l2"></i><i class="l3"></i>
      <i class="l0"></i><i class="l0"></i><i class="l1"></i><i class="l2"></i><i class="l3"></i><i class="l4"></i><i class="l0"></i>
      <i class="l1"></i><i class="l2"></i><i class="l3"></i><i class="l4"></i><i class="l0"></i><i class="l0"></i><i class="l2"></i>
      <i class="l3"></i><i class="l4"></i><i class="l0"></i><i class="l0"></i><i class="l2"></i><i class="l3"></i><i class="l4"></i>
      <i class="l0"></i><i class="l0"></i><i class="l2"></i><i class="l3"></i><i class="l4"></i><i class="l0"></i><i class="l1"></i>
      <i class="l2"></i><i class="l3"></i><i class="l4"></i><i class="l0"></i><i class="l1"></i><i class="l2"></i><i class="l0"></i>
      <i class="l4"></i><i class="l0"></i><i class="l1"></i><i class="l2"></i><i class="l0"></i><i class="l4"></i><i class="l0"></i>
      <i class="l1"></i><i class="l2"></i><i class="l0"></i><i class="l4"></i><i class="l0"></i><i class="l1"></i><i class="l2"></i>
      <i class="l0"></i><i class="l4"></i><i class="l0"></i><i class="l1"></i><i class="l2"></i><i class="l3"></i><i class="l4"></i>
      <i class="l0"></i><i class="l1"></i><i class="l2"></i><i class="l3"></i><i class="l4"></i><i class="l0"></i><i class="l1"></i>
      <i class="l2"></i><i class="l3"></i><i class="l4"></i><i class="l0"></i><i class="l1"></i><i class="l2"></i><i class="l3"></i>
      <i class="l4"></i><i class="l0"></i><i class="l1"></i><i class="l2"></i><i class="l3"></i><i class="l4"></i><i class="l0"></i>
      <i class="l1"></i><i class="l2"></i><i class="l3"></i><i class="l4"></i><i class="l0"></i><i class="l1"></i><i class="l0"></i>
      <i class="l3"></i><i class="l4"></i><i class="l0"></i><i class="l1"></i><i class="l0"></i><i class="l3"></i><i class="l4"></i>
      <i class="l0"></i><i class="l1"></i><i class="l0"></i><i class="l3"></i><i class="l4"></i><i class="l0"></i><i class="l1"></i>
      <i class="l0"></i><i class="l3"></i><i class="l4"></i><i class="l0"></i><i class="l1"></i><i class="l2"></i><i class="l3"></i>
      <i class="l4"></i><i class="l0"></i><i class="l1"></i><i class="l2"></i><i class="l3"></i><i class="l0"></i><i class="l0"></i>
      <i class="l1"></i><i class="l2"></i><i class="l3"></i><i class="l0"></i><i class="l0"></i><i class="l1"></i><i class="l2"></i>
      <i class="l3"></i><i class="l0"></i><i class="l0"></i><i class="l1"></i><i class="l2"></i><i class="l3"></i><i class="l4"></i>
      <i class="l0"></i><i class="l1"></i><i class="l2"></i><i class="l3"></i><i class="l4"></i><i class="l0"></i><i class="l0"></i>
      <i class="l2"></i><i class="l3"></i><i class="l4"></i><i class="l0"></i><i class="l0"></i><i class="l2"></i><i class="l3"></i>
      <i class="l4"></i><i class="l0"></i><i class="l0"></i><i class="l2"></i><i class="l3"></i><i class="l4"></i><i class="l0"></i>
      <i class="l0"></i><i class="l2"></i><i class="l3"></i><i class="l4"></i><i class="l0"></i><i class="l1"></i><i class="l2"></i>
      <i class="l3"></i><i class="l4"></i><i class="l0"></i><i class="l1"></i><i class="l2"></i><i class="l0"></i><i class="l4"></i>
      <i class="l0"></i><i class="l1"></i><i class="l2"></i><i class="l0"></i><i class="l4"></i><i class="l0"></i><i class="l1"></i>
      <i class="l2"></i><i class="l0"></i><i class="l4"></i><i class="l0"></i><i class="l1"></i><i class="l2"></i><i class="l3"></i>
      <i class="l4"></i><i class="l0"></i><i class="l1"></i><i class="l2"></i><i class="l3"></i><i class="l4"></i><i class="l0"></i>
      <i class="l1"></i><i class="l2"></i><i class="l3"></i><i class="l4"></i><i class="l0"></i><i class="l1"></i><i class="l2"></i>
      <i class="l3"></i><i class="l4"></i><i class="l0"></i><i class="l1"></i><i class="l2"></i><i class="l3"></i><i class="l4"></i>
      <i class="l0"></i><i class="l1"></i><i class="l2"></i><i class="l3"></i><i class="l4"></i><i class="l0"></i><i class="l1"></i>
      <i class="l2"></i><i class="l3"></i><i class="l4"></i><i class="l0"></i><i class="l1"></i><i class="l0"></i><i class="l3"></i>
      <i class="l4"></i><i class="l0"></i><i class="l1"></i><i class="l0"></i><i class="l3"></i><i class="l4"></i><i class="l0"></i>
      <i class="l1"></i><i class="l0"></i><i class="l3"></i><i class="l4"></i><i class="l0"></i><i class="l1"></i><i class="l2"></i>
      <i class="l3"></i><i class="l4"></i><i class="l0"></i><i class="l1"></i><i class="l2"></i><i class="l3"></i><i class="l0"></i>
      <i class="l0"></i><i class="l1"></i><i class="l2"></i><i class="l3"></i><i class="l0"></i><i class="l0"></i><i class="l1"></i>
      <i class="l2"></i><i class="l3"></i><i class="l0"></i><i class="l0"></i><i class="l1"></i><i class="l2"></i><i class="l3"></i>
      <i class="l0"></i><i class="l0"></i><i class="l1"></i><i class="l2"></i><i class="l3"></i><i class="l4"></i><i class="l0"></i>
      <i class="l1"></i><i class="l2"></i><i class="l3"></i><i class="l4"></i><i class="l0"></i><i class="l0"></i><i class="l2"></i>
      <i class="l3"></i><i class="l4"></i><i class="l0"></i><i class="l0"></i><i class="l2"></i><i class="l3"></i><i class="l4"></i>
      <i class="l0"></i><i class="l0"></i><i class="l2"></i><i class="l3"></i><i class="l4"></i><i class="l0"></i><i class="l1"></i>
      <i class="l2"></i><i class="l3"></i><i class="l4"></i><i class="l0"></i><i class="l1"></i><i class="l2"></i><i class="l0"></i>
      <i class="l4"></i><i class="l0"></i><i class="l1"></i><i class="l2"></i><i class="l0"></i><i class="l4"></i><i class="l0"></i>
      <i class="l1"></i><i class="l2"></i><i class="l0"></i><i class="l4"></i><i class="l0"></i><i class="l1"></i><i class="l2"></i>
      <i class="l0"></i><i class="l4"></i><i class="l0"></i><i class="l1"></i><i class="l2"></i><i class="l3"></i><i class="l4"></i>
      <i class="l0"></i><i class="l1"></i><i class="l2"></i><i class="l3"></i><i class="l4"></i><i class="l0"></i><i class="l1"></i>
      <i class="l2"></i><i class="l3"></i><i class="l4"></i><i class="l0"></i><i class="l1"></i><i class="l2"></i><i class="l3"></i>
      </div>
    </div>
  </div>
  <p class="legend d-flex align-items-center justify-content-end gap-2 mt-3 mb-0 text-muted-hm" style="font-size:.72rem"><span>Less</span><span aria-hidden="true" class="d-contents" style="display:contents"><i class="l0"></i><i class="l1"></i><i class="l2"></i><i class="l3"></i><i class="l4"></i></span><span>More</span></p>
  <div class="visually-hidden"><table class="table">
    <caption>Commits per month, September 2025 to August 2026</caption>
    <thead><tr><th scope="col">Month</th><th scope="col">Commits</th></tr></thead>
    <tbody>
      <tr><th scope="row">September 2025</th><td>96</td></tr>
      <tr><th scope="row">October 2025</th><td>112</td></tr>
      <tr><th scope="row">November 2025</th><td>88</td></tr>
      <tr><th scope="row">December 2025</th><td>64</td></tr>
      <tr><th scope="row">January 2026</th><td>101</td></tr>
      <tr><th scope="row">February 2026</th><td>118</td></tr>
      <tr><th scope="row">March 2026</th><td>142</td></tr>
      <tr><th scope="row">April 2026</th><td>127</td></tr>
      <tr><th scope="row">May 2026</th><td>109</td></tr>
      <tr><th scope="row">June 2026</th><td>115</td></tr>
      <tr><th scope="row">July 2026</th><td>98</td></tr>
      <tr><th scope="row">August 2026</th><td>114</td></tr>
    </tbody>
  </table></div>
</div>
CSS
/* Bootstrap card and utilities; the week grid itself is plain CSS grid. The text alternative is a .visually-hidden .table. */
.heat{--hm-0:#eaeef3;--hm-1:#c9e3d0;--hm-2:#86c99b;--hm-3:#41a862;--hm-4:#1e7a41;--hm-muted:#5f6b7c;
  max-width:840px;padding:22px 24px 20px;border:0;border-radius:16px;box-shadow:0 14px 34px -18px rgba(18,24,40,.25)}
.heat .scroll{padding:2px;border-radius:6px}
.heat .scroll:focus-visible{outline:2px solid #6d28d9;outline-offset:2px}
.heat .months{display:grid;grid-auto-flow:column;grid-auto-columns:1fr;font-size:.66rem;min-width:700px;padding-left:26px}
.heat .wk{min-width:700px}
.heat .dows{display:grid;grid-template-rows:repeat(7,1fr);gap:3px;font-size:.6rem;width:20px;align-items:center}
.heat .cells{display:grid;grid-template-rows:repeat(7,1fr);grid-auto-flow:column;grid-auto-columns:1fr;gap:3px}
.heat .cells i,.heat .legend i{border-radius:2.5px;font-style:normal}
.heat .cells i{aspect-ratio:1;min-height:9px}
.heat .legend i{width:11px;height:11px}
.heat .l0{background:var(--hm-0)}.heat .l1{background:var(--hm-1)}.heat .l2{background:var(--hm-2)}.heat .l3{background:var(--hm-3)}.heat .l4{background:var(--hm-4)}
.heat .text-muted-hm{color:var(--hm-muted)}

Tailwind 4 code

Requires: Tailwind CSS 4

HTML
<div class="heat w-full max-w-[840px] rounded-2xl bg-white px-6 pt-[22px] pb-5 shadow-[0_14px_34px_-18px_rgba(18,24,40,.25)]">
  <h2 class="mb-[3px] text-[.95rem] font-bold">1,284 commits in the last year</h2>
  <p class="mb-4 text-[.79rem] text-hm-muted">Longest streak 34 days · Busiest day 12 March</p>
  <div class="overflow-x-auto rounded-md p-0.5 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[#6d28d9]" tabindex="0" role="region" aria-label="Activity heatmap, scrolls sideways">
    <div class="mb-[5px] grid min-w-[700px] auto-cols-fr grid-flow-col pl-[26px] text-[.66rem] font-bold text-hm-muted" aria-hidden="true"><span>Sep</span><span>Oct</span><span>Nov</span><span>Dec</span><span>Jan</span><span>Feb</span><span>Mar</span><span>Apr</span><span>May</span><span>Jun</span><span>Jul</span><span>Aug</span></div>
    <div class="flex min-w-[700px] gap-1.5">
      <div class="grid w-5 grid-rows-7 items-center gap-[3px] text-[.6rem] font-bold text-hm-muted" aria-hidden="true"><span></span><span>M</span><span></span><span>W</span><span></span><span>F</span><span></span></div>
      <div class="grid flex-1 auto-cols-fr grid-flow-col grid-rows-7 gap-[3px] *:aspect-square *:min-h-[9px] *:rounded-[2.5px]" role="img" aria-label="Daily commits for the last 52 weeks, shaded in five levels from none to most. Monthly totals are in the table that follows.">
      <i class="bg-hm-0"></i><i class="bg-hm-1"></i><i class="bg-hm-2"></i><i class="bg-hm-3"></i><i class="bg-hm-4"></i><i class="bg-hm-0"></i><i class="bg-hm-1"></i>
      <i class="bg-hm-2"></i><i class="bg-hm-3"></i><i class="bg-hm-4"></i><i class="bg-hm-0"></i><i class="bg-hm-1"></i><i class="bg-hm-0"></i><i class="bg-hm-3"></i>
      <i class="bg-hm-4"></i><i class="bg-hm-0"></i><i class="bg-hm-1"></i><i class="bg-hm-0"></i><i class="bg-hm-3"></i><i class="bg-hm-4"></i><i class="bg-hm-0"></i>
      <i class="bg-hm-1"></i><i class="bg-hm-0"></i><i class="bg-hm-3"></i><i class="bg-hm-4"></i><i class="bg-hm-0"></i><i class="bg-hm-1"></i><i class="bg-hm-2"></i>
      <i class="bg-hm-3"></i><i class="bg-hm-4"></i><i class="bg-hm-0"></i><i class="bg-hm-1"></i><i class="bg-hm-2"></i><i class="bg-hm-3"></i><i class="bg-hm-0"></i>
      <i class="bg-hm-0"></i><i class="bg-hm-1"></i><i class="bg-hm-2"></i><i class="bg-hm-3"></i><i class="bg-hm-0"></i><i class="bg-hm-0"></i><i class="bg-hm-1"></i>
      <i class="bg-hm-2"></i><i class="bg-hm-3"></i><i class="bg-hm-0"></i><i class="bg-hm-0"></i><i class="bg-hm-1"></i><i class="bg-hm-2"></i><i class="bg-hm-3"></i>
      <i class="bg-hm-0"></i><i class="bg-hm-0"></i><i class="bg-hm-1"></i><i class="bg-hm-2"></i><i class="bg-hm-3"></i><i class="bg-hm-4"></i><i class="bg-hm-0"></i>
      <i class="bg-hm-1"></i><i class="bg-hm-2"></i><i class="bg-hm-3"></i><i class="bg-hm-4"></i><i class="bg-hm-0"></i><i class="bg-hm-0"></i><i class="bg-hm-2"></i>
      <i class="bg-hm-3"></i><i class="bg-hm-4"></i><i class="bg-hm-0"></i><i class="bg-hm-0"></i><i class="bg-hm-2"></i><i class="bg-hm-3"></i><i class="bg-hm-4"></i>
      <i class="bg-hm-0"></i><i class="bg-hm-0"></i><i class="bg-hm-2"></i><i class="bg-hm-3"></i><i class="bg-hm-4"></i><i class="bg-hm-0"></i><i class="bg-hm-1"></i>
      <i class="bg-hm-2"></i><i class="bg-hm-3"></i><i class="bg-hm-4"></i><i class="bg-hm-0"></i><i class="bg-hm-1"></i><i class="bg-hm-2"></i><i class="bg-hm-0"></i>
      <i class="bg-hm-4"></i><i class="bg-hm-0"></i><i class="bg-hm-1"></i><i class="bg-hm-2"></i><i class="bg-hm-0"></i><i class="bg-hm-4"></i><i class="bg-hm-0"></i>
      <i class="bg-hm-1"></i><i class="bg-hm-2"></i><i class="bg-hm-0"></i><i class="bg-hm-4"></i><i class="bg-hm-0"></i><i class="bg-hm-1"></i><i class="bg-hm-2"></i>
      <i class="bg-hm-0"></i><i class="bg-hm-4"></i><i class="bg-hm-0"></i><i class="bg-hm-1"></i><i class="bg-hm-2"></i><i class="bg-hm-3"></i><i class="bg-hm-4"></i>
      <i class="bg-hm-0"></i><i class="bg-hm-1"></i><i class="bg-hm-2"></i><i class="bg-hm-3"></i><i class="bg-hm-4"></i><i class="bg-hm-0"></i><i class="bg-hm-1"></i>
      <i class="bg-hm-2"></i><i class="bg-hm-3"></i><i class="bg-hm-4"></i><i class="bg-hm-0"></i><i class="bg-hm-1"></i><i class="bg-hm-2"></i><i class="bg-hm-3"></i>
      <i class="bg-hm-4"></i><i class="bg-hm-0"></i><i class="bg-hm-1"></i><i class="bg-hm-2"></i><i class="bg-hm-3"></i><i class="bg-hm-4"></i><i class="bg-hm-0"></i>
      <i class="bg-hm-1"></i><i class="bg-hm-2"></i><i class="bg-hm-3"></i><i class="bg-hm-4"></i><i class="bg-hm-0"></i><i class="bg-hm-1"></i><i class="bg-hm-0"></i>
      <i class="bg-hm-3"></i><i class="bg-hm-4"></i><i class="bg-hm-0"></i><i class="bg-hm-1"></i><i class="bg-hm-0"></i><i class="bg-hm-3"></i><i class="bg-hm-4"></i>
      <i class="bg-hm-0"></i><i class="bg-hm-1"></i><i class="bg-hm-0"></i><i class="bg-hm-3"></i><i class="bg-hm-4"></i><i class="bg-hm-0"></i><i class="bg-hm-1"></i>
      <i class="bg-hm-0"></i><i class="bg-hm-3"></i><i class="bg-hm-4"></i><i class="bg-hm-0"></i><i class="bg-hm-1"></i><i class="bg-hm-2"></i><i class="bg-hm-3"></i>
      <i class="bg-hm-4"></i><i class="bg-hm-0"></i><i class="bg-hm-1"></i><i class="bg-hm-2"></i><i class="bg-hm-3"></i><i class="bg-hm-0"></i><i class="bg-hm-0"></i>
      <i class="bg-hm-1"></i><i class="bg-hm-2"></i><i class="bg-hm-3"></i><i class="bg-hm-0"></i><i class="bg-hm-0"></i><i class="bg-hm-1"></i><i class="bg-hm-2"></i>
      <i class="bg-hm-3"></i><i class="bg-hm-0"></i><i class="bg-hm-0"></i><i class="bg-hm-1"></i><i class="bg-hm-2"></i><i class="bg-hm-3"></i><i class="bg-hm-4"></i>
      <i class="bg-hm-0"></i><i class="bg-hm-1"></i><i class="bg-hm-2"></i><i class="bg-hm-3"></i><i class="bg-hm-4"></i><i class="bg-hm-0"></i><i class="bg-hm-0"></i>
      <i class="bg-hm-2"></i><i class="bg-hm-3"></i><i class="bg-hm-4"></i><i class="bg-hm-0"></i><i class="bg-hm-0"></i><i class="bg-hm-2"></i><i class="bg-hm-3"></i>
      <i class="bg-hm-4"></i><i class="bg-hm-0"></i><i class="bg-hm-0"></i><i class="bg-hm-2"></i><i class="bg-hm-3"></i><i class="bg-hm-4"></i><i class="bg-hm-0"></i>
      <i class="bg-hm-0"></i><i class="bg-hm-2"></i><i class="bg-hm-3"></i><i class="bg-hm-4"></i><i class="bg-hm-0"></i><i class="bg-hm-1"></i><i class="bg-hm-2"></i>
      <i class="bg-hm-3"></i><i class="bg-hm-4"></i><i class="bg-hm-0"></i><i class="bg-hm-1"></i><i class="bg-hm-2"></i><i class="bg-hm-0"></i><i class="bg-hm-4"></i>
      <i class="bg-hm-0"></i><i class="bg-hm-1"></i><i class="bg-hm-2"></i><i class="bg-hm-0"></i><i class="bg-hm-4"></i><i class="bg-hm-0"></i><i class="bg-hm-1"></i>
      <i class="bg-hm-2"></i><i class="bg-hm-0"></i><i class="bg-hm-4"></i><i class="bg-hm-0"></i><i class="bg-hm-1"></i><i class="bg-hm-2"></i><i class="bg-hm-3"></i>
      <i class="bg-hm-4"></i><i class="bg-hm-0"></i><i class="bg-hm-1"></i><i class="bg-hm-2"></i><i class="bg-hm-3"></i><i class="bg-hm-4"></i><i class="bg-hm-0"></i>
      <i class="bg-hm-1"></i><i class="bg-hm-2"></i><i class="bg-hm-3"></i><i class="bg-hm-4"></i><i class="bg-hm-0"></i><i class="bg-hm-1"></i><i class="bg-hm-2"></i>
      <i class="bg-hm-3"></i><i class="bg-hm-4"></i><i class="bg-hm-0"></i><i class="bg-hm-1"></i><i class="bg-hm-2"></i><i class="bg-hm-3"></i><i class="bg-hm-4"></i>
      <i class="bg-hm-0"></i><i class="bg-hm-1"></i><i class="bg-hm-2"></i><i class="bg-hm-3"></i><i class="bg-hm-4"></i><i class="bg-hm-0"></i><i class="bg-hm-1"></i>
      <i class="bg-hm-2"></i><i class="bg-hm-3"></i><i class="bg-hm-4"></i><i class="bg-hm-0"></i><i class="bg-hm-1"></i><i class="bg-hm-0"></i><i class="bg-hm-3"></i>
      <i class="bg-hm-4"></i><i class="bg-hm-0"></i><i class="bg-hm-1"></i><i class="bg-hm-0"></i><i class="bg-hm-3"></i><i class="bg-hm-4"></i><i class="bg-hm-0"></i>
      <i class="bg-hm-1"></i><i class="bg-hm-0"></i><i class="bg-hm-3"></i><i class="bg-hm-4"></i><i class="bg-hm-0"></i><i class="bg-hm-1"></i><i class="bg-hm-2"></i>
      <i class="bg-hm-3"></i><i class="bg-hm-4"></i><i class="bg-hm-0"></i><i class="bg-hm-1"></i><i class="bg-hm-2"></i><i class="bg-hm-3"></i><i class="bg-hm-0"></i>
      <i class="bg-hm-0"></i><i class="bg-hm-1"></i><i class="bg-hm-2"></i><i class="bg-hm-3"></i><i class="bg-hm-0"></i><i class="bg-hm-0"></i><i class="bg-hm-1"></i>
      <i class="bg-hm-2"></i><i class="bg-hm-3"></i><i class="bg-hm-0"></i><i class="bg-hm-0"></i><i class="bg-hm-1"></i><i class="bg-hm-2"></i><i class="bg-hm-3"></i>
      <i class="bg-hm-0"></i><i class="bg-hm-0"></i><i class="bg-hm-1"></i><i class="bg-hm-2"></i><i class="bg-hm-3"></i><i class="bg-hm-4"></i><i class="bg-hm-0"></i>
      <i class="bg-hm-1"></i><i class="bg-hm-2"></i><i class="bg-hm-3"></i><i class="bg-hm-4"></i><i class="bg-hm-0"></i><i class="bg-hm-0"></i><i class="bg-hm-2"></i>
      <i class="bg-hm-3"></i><i class="bg-hm-4"></i><i class="bg-hm-0"></i><i class="bg-hm-0"></i><i class="bg-hm-2"></i><i class="bg-hm-3"></i><i class="bg-hm-4"></i>
      <i class="bg-hm-0"></i><i class="bg-hm-0"></i><i class="bg-hm-2"></i><i class="bg-hm-3"></i><i class="bg-hm-4"></i><i class="bg-hm-0"></i><i class="bg-hm-1"></i>
      <i class="bg-hm-2"></i><i class="bg-hm-3"></i><i class="bg-hm-4"></i><i class="bg-hm-0"></i><i class="bg-hm-1"></i><i class="bg-hm-2"></i><i class="bg-hm-0"></i>
      <i class="bg-hm-4"></i><i class="bg-hm-0"></i><i class="bg-hm-1"></i><i class="bg-hm-2"></i><i class="bg-hm-0"></i><i class="bg-hm-4"></i><i class="bg-hm-0"></i>
      <i class="bg-hm-1"></i><i class="bg-hm-2"></i><i class="bg-hm-0"></i><i class="bg-hm-4"></i><i class="bg-hm-0"></i><i class="bg-hm-1"></i><i class="bg-hm-2"></i>
      <i class="bg-hm-0"></i><i class="bg-hm-4"></i><i class="bg-hm-0"></i><i class="bg-hm-1"></i><i class="bg-hm-2"></i><i class="bg-hm-3"></i><i class="bg-hm-4"></i>
      <i class="bg-hm-0"></i><i class="bg-hm-1"></i><i class="bg-hm-2"></i><i class="bg-hm-3"></i><i class="bg-hm-4"></i><i class="bg-hm-0"></i><i class="bg-hm-1"></i>
      <i class="bg-hm-2"></i><i class="bg-hm-3"></i><i class="bg-hm-4"></i><i class="bg-hm-0"></i><i class="bg-hm-1"></i><i class="bg-hm-2"></i><i class="bg-hm-3"></i>
      </div>
    </div>
  </div>
  <p class="mt-3.5 flex items-center justify-end gap-1.5 text-[.72rem] text-hm-muted"><span>Less</span><span aria-hidden="true" class="contents *:size-[11px] *:rounded-[2.5px]"><i class="bg-hm-0"></i><i class="bg-hm-1"></i><i class="bg-hm-2"></i><i class="bg-hm-3"></i><i class="bg-hm-4"></i></span><span>More</span></p>
  <div class="sr-only"><table>
    <caption>Commits per month, September 2025 to August 2026</caption>
    <thead><tr><th scope="col">Month</th><th scope="col">Commits</th></tr></thead>
    <tbody>
      <tr><th scope="row">September 2025</th><td>96</td></tr>
      <tr><th scope="row">October 2025</th><td>112</td></tr>
      <tr><th scope="row">November 2025</th><td>88</td></tr>
      <tr><th scope="row">December 2025</th><td>64</td></tr>
      <tr><th scope="row">January 2026</th><td>101</td></tr>
      <tr><th scope="row">February 2026</th><td>118</td></tr>
      <tr><th scope="row">March 2026</th><td>142</td></tr>
      <tr><th scope="row">April 2026</th><td>127</td></tr>
      <tr><th scope="row">May 2026</th><td>109</td></tr>
      <tr><th scope="row">June 2026</th><td>115</td></tr>
      <tr><th scope="row">July 2026</th><td>98</td></tr>
      <tr><th scope="row">August 2026</th><td>114</td></tr>
    </tbody>
  </table></div>
</div>
CSS
@theme {
  --color-hm-0: #eaeef3;
  --color-hm-1: #c9e3d0;
  --color-hm-2: #86c99b;
  --color-hm-3: #41a862;
  --color-hm-4: #1e7a41;
  --color-hm-muted: #5f6b7c;
}

About this set

A contribution-style heatmap: a year of days laid out as 52 week columns of seven cells, each shaded in one of five greens by how much happened that day, with month labels across the top, Monday, Wednesday and Friday down the side and a Less to More legend. It suits developer profiles, habit trackers, learning streaks and any dashboard that shows a year of daily activity at a glance. The grid is CSS grid with grid-auto-flow: column, so cells fill week by week, and the shade is one class per cell. Because a field of coloured squares means nothing to a screen reader, the grid is exposed as a single image with a descriptive label, and a visually hidden table lists the commit total for every month as text. The heatmap sits in a horizontally scrollable region with a minimum width of 700 pixels, so the cells stay readable on a phone instead of shrinking to dots; that region is focusable so it can be scrolled with the keyboard. The Bootstrap version uses a card and utilities around the same grid, and the Tailwind version sets the five shades as theme colours.

What’s included

  • 52 weeks by 7 days on CSS grid, filled column by column
  • Five shades from a single set of custom properties
  • Visually hidden table of monthly totals as the text alternative
  • Keyboard-scrollable region keeps cells legible at 375px
  • Plain CSS, Bootstrap and Tailwind versions of the same design

Accessibility

The cell grid has role="img" with a label that summarises it, and the same data is available as a hidden table of commits per month with a caption and headers. The month and weekday labels are hidden from assistive tech because the table covers them. The scrollable region has tabindex="0", an aria-label and a 2px violet focus outline. Nothing animates.

Customise it

Change --hm-0 to --hm-4 (the five shades) and --hm-muted on .heat in plain CSS and Bootstrap, or the --color-hm-* theme colours in Tailwind. Cell size follows the container; the min-width of 700px sets when scrolling starts.