Skip to content

Gallery / charts / Heat calendar

Heat calendar

GitHub-style heat calendar cascading in diagonally

charts intermediate chartheatmapcalendarcascade
Live preview

Techniques: --sg-i index variables · nth-of-type indexing · fill-opacity levels · css rect geometry

Customizeupdates preview, code & clipboard
#7F77DD
260px
1.4s
Code snippets/charts/chart-heat-calendar.html
<!--
  ============================================================
  SVGarden — https://www.svgarden.dev
  Author : Simon-Pierre Boucher
  Contact: contact@spboucher.ai
  File   : snippets/charts/chart-heat-calendar.html
  Desc   : GitHub-style heat calendar cascading in diagonally
  ============================================================
-->
<div class="sg-chart-heat-calendar" style="--sg-color:#7F77DD; --sg-size:260px; --sg-duration:1.4s;">
  <svg viewBox="0 0 210 96" role="img" aria-label="Activity heat calendar, 14 weeks by 7 days, busiest midweek">
    <title>Contribution heat calendar</title>
    <text class="sg-chart-heat-calendar-day" x="18" y="23">M</text>
    <text class="sg-chart-heat-calendar-day" x="18" y="49">W</text>
    <text class="sg-chart-heat-calendar-day" x="18" y="75">F</text>
    <g class="sg-chart-heat-calendar-row" style="--sg-r:0"><rect x="22" y="2" class="sg-chart-heat-calendar-l0"/><rect x="35" y="2" class="sg-chart-heat-calendar-l0"/><rect x="48" y="2" class="sg-chart-heat-calendar-l1"/><rect x="61" y="2" class="sg-chart-heat-calendar-l0"/><rect x="74" y="2" class="sg-chart-heat-calendar-l0"/><rect x="87" y="2" class="sg-chart-heat-calendar-l1"/><rect x="100" y="2" class="sg-chart-heat-calendar-l0"/><rect x="113" y="2" class="sg-chart-heat-calendar-l0"/><rect x="126" y="2" class="sg-chart-heat-calendar-l0"/><rect x="139" y="2" class="sg-chart-heat-calendar-l1"/><rect x="152" y="2" class="sg-chart-heat-calendar-l0"/><rect x="165" y="2" class="sg-chart-heat-calendar-l0"/><rect x="178" y="2" class="sg-chart-heat-calendar-l1"/><rect x="191" y="2" class="sg-chart-heat-calendar-l0"/></g>
    <g class="sg-chart-heat-calendar-row" style="--sg-r:1"><rect x="22" y="15" class="sg-chart-heat-calendar-l1"/><rect x="35" y="15" class="sg-chart-heat-calendar-l2"/><rect x="48" y="15" class="sg-chart-heat-calendar-l1"/><rect x="61" y="15" class="sg-chart-heat-calendar-l2"/><rect x="74" y="15" class="sg-chart-heat-calendar-l3"/><rect x="87" y="15" class="sg-chart-heat-calendar-l1"/><rect x="100" y="15" class="sg-chart-heat-calendar-l2"/><rect x="113" y="15" class="sg-chart-heat-calendar-l1"/><rect x="126" y="15" class="sg-chart-heat-calendar-l3"/><rect x="139" y="15" class="sg-chart-heat-calendar-l2"/><rect x="152" y="15" class="sg-chart-heat-calendar-l1"/><rect x="165" y="15" class="sg-chart-heat-calendar-l2"/><rect x="178" y="15" class="sg-chart-heat-calendar-l2"/><rect x="191" y="15" class="sg-chart-heat-calendar-l1"/></g>
    <g class="sg-chart-heat-calendar-row" style="--sg-r:2"><rect x="22" y="28" class="sg-chart-heat-calendar-l2"/><rect x="35" y="28" class="sg-chart-heat-calendar-l1"/><rect x="48" y="28" class="sg-chart-heat-calendar-l3"/><rect x="61" y="28" class="sg-chart-heat-calendar-l2"/><rect x="74" y="28" class="sg-chart-heat-calendar-l1"/><rect x="87" y="28" class="sg-chart-heat-calendar-l2"/><rect x="100" y="28" class="sg-chart-heat-calendar-l3"/><rect x="113" y="28" class="sg-chart-heat-calendar-l2"/><rect x="126" y="28" class="sg-chart-heat-calendar-l1"/><rect x="139" y="28" class="sg-chart-heat-calendar-l3"/><rect x="152" y="28" class="sg-chart-heat-calendar-l2"/><rect x="165" y="28" class="sg-chart-heat-calendar-l1"/><rect x="178" y="28" class="sg-chart-heat-calendar-l3"/><rect x="191" y="28" class="sg-chart-heat-calendar-l2"/></g>
    <g class="sg-chart-heat-calendar-row" style="--sg-r:3"><rect x="22" y="41" class="sg-chart-heat-calendar-l1"/><rect x="35" y="41" class="sg-chart-heat-calendar-l3"/><rect x="48" y="41" class="sg-chart-heat-calendar-l2"/><rect x="61" y="41" class="sg-chart-heat-calendar-l3"/><rect x="74" y="41" class="sg-chart-heat-calendar-l2"/><rect x="87" y="41" class="sg-chart-heat-calendar-l3"/><rect x="100" y="41" class="sg-chart-heat-calendar-l1"/><rect x="113" y="41" class="sg-chart-heat-calendar-l3"/><rect x="126" y="41" class="sg-chart-heat-calendar-l2"/><rect x="139" y="41" class="sg-chart-heat-calendar-l2"/><rect x="152" y="41" class="sg-chart-heat-calendar-l3"/><rect x="165" y="41" class="sg-chart-heat-calendar-l3"/><rect x="178" y="41" class="sg-chart-heat-calendar-l1"/><rect x="191" y="41" class="sg-chart-heat-calendar-l3"/></g>
    <g class="sg-chart-heat-calendar-row" style="--sg-r:4"><rect x="22" y="54" class="sg-chart-heat-calendar-l2"/><rect x="35" y="54" class="sg-chart-heat-calendar-l2"/><rect x="48" y="54" class="sg-chart-heat-calendar-l1"/><rect x="61" y="54" class="sg-chart-heat-calendar-l1"/><rect x="74" y="54" class="sg-chart-heat-calendar-l3"/><rect x="87" y="54" class="sg-chart-heat-calendar-l2"/><rect x="100" y="54" class="sg-chart-heat-calendar-l2"/><rect x="113" y="54" class="sg-chart-heat-calendar-l3"/><rect x="126" y="54" class="sg-chart-heat-calendar-l1"/><rect x="139" y="54" class="sg-chart-heat-calendar-l2"/><rect x="152" y="54" class="sg-chart-heat-calendar-l3"/><rect x="165" y="54" class="sg-chart-heat-calendar-l1"/><rect x="178" y="54" class="sg-chart-heat-calendar-l2"/><rect x="191" y="54" class="sg-chart-heat-calendar-l3"/></g>
    <g class="sg-chart-heat-calendar-row" style="--sg-r:5"><rect x="22" y="67" class="sg-chart-heat-calendar-l3"/><rect x="35" y="67" class="sg-chart-heat-calendar-l1"/><rect x="48" y="67" class="sg-chart-heat-calendar-l2"/><rect x="61" y="67" class="sg-chart-heat-calendar-l2"/><rect x="74" y="67" class="sg-chart-heat-calendar-l2"/><rect x="87" y="67" class="sg-chart-heat-calendar-l1"/><rect x="100" y="67" class="sg-chart-heat-calendar-l3"/><rect x="113" y="67" class="sg-chart-heat-calendar-l1"/><rect x="126" y="67" class="sg-chart-heat-calendar-l2"/><rect x="139" y="67" class="sg-chart-heat-calendar-l1"/><rect x="152" y="67" class="sg-chart-heat-calendar-l1"/><rect x="165" y="67" class="sg-chart-heat-calendar-l2"/><rect x="178" y="67" class="sg-chart-heat-calendar-l3"/><rect x="191" y="67" class="sg-chart-heat-calendar-l1"/></g>
    <g class="sg-chart-heat-calendar-row" style="--sg-r:6"><rect x="22" y="80" class="sg-chart-heat-calendar-l0"/><rect x="35" y="80" class="sg-chart-heat-calendar-l1"/><rect x="48" y="80" class="sg-chart-heat-calendar-l0"/><rect x="61" y="80" class="sg-chart-heat-calendar-l0"/><rect x="74" y="80" class="sg-chart-heat-calendar-l1"/><rect x="87" y="80" class="sg-chart-heat-calendar-l0"/><rect x="100" y="80" class="sg-chart-heat-calendar-l0"/><rect x="113" y="80" class="sg-chart-heat-calendar-l1"/><rect x="126" y="80" class="sg-chart-heat-calendar-l0"/><rect x="139" y="80" class="sg-chart-heat-calendar-l0"/><rect x="152" y="80" class="sg-chart-heat-calendar-l2"/><rect x="165" y="80" class="sg-chart-heat-calendar-l0"/><rect x="178" y="80" class="sg-chart-heat-calendar-l0"/><rect x="191" y="80" class="sg-chart-heat-calendar-l1"/></g>
  </svg>
</div>
<style>
  .sg-chart-heat-calendar {
    width: var(--sg-size);
  }
  .sg-chart-heat-calendar svg {
    display: block;
    width: 100%;
    font-family: inherit;
  }
  .sg-chart-heat-calendar-day {
    font-size: 7px;
    fill: currentColor;
    opacity: 0.55;
    text-anchor: end;
  }
  .sg-chart-heat-calendar rect {
    width: 10px;
    height: 10px;
    rx: 2px;
    fill: var(--sg-color);
    transform-box: fill-box;
    transform-origin: center;
    animation: sg-chart-heat-calendar-pop 0.35s ease-out both;
    animation-delay: calc((var(--sg-r) + var(--sg-c)) * var(--sg-duration) / 26);
  }
  .sg-chart-heat-calendar rect:nth-of-type(1)  { --sg-c: 0; }
  .sg-chart-heat-calendar rect:nth-of-type(2)  { --sg-c: 1; }
  .sg-chart-heat-calendar rect:nth-of-type(3)  { --sg-c: 2; }
  .sg-chart-heat-calendar rect:nth-of-type(4)  { --sg-c: 3; }
  .sg-chart-heat-calendar rect:nth-of-type(5)  { --sg-c: 4; }
  .sg-chart-heat-calendar rect:nth-of-type(6)  { --sg-c: 5; }
  .sg-chart-heat-calendar rect:nth-of-type(7)  { --sg-c: 6; }
  .sg-chart-heat-calendar rect:nth-of-type(8)  { --sg-c: 7; }
  .sg-chart-heat-calendar rect:nth-of-type(9)  { --sg-c: 8; }
  .sg-chart-heat-calendar rect:nth-of-type(10) { --sg-c: 9; }
  .sg-chart-heat-calendar rect:nth-of-type(11) { --sg-c: 10; }
  .sg-chart-heat-calendar rect:nth-of-type(12) { --sg-c: 11; }
  .sg-chart-heat-calendar rect:nth-of-type(13) { --sg-c: 12; }
  .sg-chart-heat-calendar rect:nth-of-type(14) { --sg-c: 13; }
  .sg-chart-heat-calendar-l0 { fill-opacity: 0.12; }
  .sg-chart-heat-calendar-l1 { fill-opacity: 0.35; }
  .sg-chart-heat-calendar-l2 { fill-opacity: 0.6; }
  .sg-chart-heat-calendar-l3 { fill-opacity: 0.9; }
  @keyframes sg-chart-heat-calendar-pop {
    from { opacity: 0; transform: scale(0.4); }
    to   { opacity: 1; transform: scale(1); }
  }
</style>

More charts