NS Design System
v3.0.0 · 257 tokens

153Bar charts

The workhorse: comparison and time. Bars are ≤24px thick with a rounded data-end and a square baseline, grow from zero on load, and the whole column is the tooltip's hit target.

Column — single series

One series needs no legend: the title names it. Hover for the tooltip; bars animate up on load (and hold still under reduced motion).

Course completionsweekly
W1 · 38
W2 · 52
W3 · 46
W4 · 64
W5 · 58
W6 · 82
W1W2W3W4W5W6
markup
<figure class="ns-chart">
  <div class="ns-chart__head"><span class="ns-chart__title">Course completions</span><span class="ns-chart__sub">weekly</span></div>
  <div class="ns-chart__plot">
    <div class="ns-chart__col" tabindex="0" style="--v:38%">
      <span class="ns-chart__tip">W1 · 38</span>
      <div class="ns-chart__bar"></div>
    </div>
    <div class="ns-chart__col" tabindex="0" style="--v:52%">
      <span class="ns-chart__tip">W2 · 52</span>
      <div class="ns-chart__bar"></div>
    </div>
    <div class="ns-chart__col" tabindex="0" style="--v:46%">
      <span class="ns-chart__tip">W3 · 46</span>
      <div class="ns-chart__bar"></div>
    </div>
    <div class="ns-chart__col" tabindex="0" style="--v:64%">
      <span class="ns-chart__tip">W4 · 64</span>
      <div class="ns-chart__bar"></div>
    </div>
    <div class="ns-chart__col" tabindex="0" style="--v:58%">
      <span class="ns-chart__tip">W5 · 58</span>
      <div class="ns-chart__bar"></div>
    </div>
    <div class="ns-chart__col" tabindex="0" style="--v:82%">
      <span class="ns-chart__tip">W6 · 82</span>
      <div class="ns-chart__bar"></div>
    </div>
  </div>
  <div class="ns-chart__x"><span>W1</span><span>W2</span><span>W3</span><span>W4</span><span>W5</span><span>W6</span></div>
</figure>

Sizes

Three plot heights: sm for cards and rails, md default, lg for a dashboard's lead chart.

Small6rem
W1 · 38
W2 · 52
W3 · 46
W4 · 64
Medium10rem · default
W1 · 38
W2 · 52
W3 · 46
W4 · 64
Large15rem
W1 · 38
W2 · 52
W3 · 46
W4 · 64
markup
<div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(min(14rem,100%),1fr));gap:var(--gap-grid);inline-size:100%">
  <figure class="ns-chart ns-chart--sm">
    <div class="ns-chart__head"><span class="ns-chart__title">Small</span><span class="ns-chart__sub">6rem</span></div>
    <div class="ns-chart__plot">
    <div class="ns-chart__col" tabindex="0" style="--v:38%">
      <span class="ns-chart__tip">W1 · 38</span>
      <div class="ns-chart__bar"></div>
    </div>
    <div class="ns-chart__col" tabindex="0" style="--v:52%">
      <span class="ns-chart__tip">W2 · 52</span>
      <div class="ns-chart__bar"></div>
    </div>
    <div class="ns-chart__col" tabindex="0" style="--v:46%">
      <span class="ns-chart__tip">W3 · 46</span>
      <div class="ns-chart__bar"></div>
    </div>
    <div class="ns-chart__col" tabindex="0" style="--v:64%">
      <span class="ns-chart__tip">W4 · 64</span>
      <div class="ns-chart__bar"></div>
    </div>
    </div>
  </figure>
  <figure class="ns-chart">
    <div class="ns-chart__head"><span class="ns-chart__title">Medium</span><span class="ns-chart__sub">10rem · default</span></div>
    <div class="ns-chart__plot">
    <div class="ns-chart__col" tabindex="0" style="--v:38%">
      <span class="ns-chart__tip">W1 · 38</span>
      <div class="ns-chart__bar"></div>
    </div>
    <div class="ns-chart__col" tabindex="0" style="--v:52%">
      <span class="ns-chart__tip">W2 · 52</span>
      <div class="ns-chart__bar"></div>
    </div>
    <div class="ns-chart__col" tabindex="0" style="--v:46%">
      <span class="ns-chart__tip">W3 · 46</span>
      <div class="ns-chart__bar"></div>
    </div>
    <div class="ns-chart__col" tabindex="0" style="--v:64%">
      <span class="ns-chart__tip">W4 · 64</span>
      <div class="ns-chart__bar"></div>
    </div>
    </div>
  </figure>
  <figure class="ns-chart ns-chart--lg">
    <div class="ns-chart__head"><span class="ns-chart__title">Large</span><span class="ns-chart__sub">15rem</span></div>
    <div class="ns-chart__plot">
    <div class="ns-chart__col" tabindex="0" style="--v:38%">
      <span class="ns-chart__tip">W1 · 38</span>
      <div class="ns-chart__bar"></div>
    </div>
    <div class="ns-chart__col" tabindex="0" style="--v:52%">
      <span class="ns-chart__tip">W2 · 52</span>
      <div class="ns-chart__bar"></div>
    </div>
    <div class="ns-chart__col" tabindex="0" style="--v:46%">
      <span class="ns-chart__tip">W3 · 46</span>
      <div class="ns-chart__bar"></div>
    </div>
    <div class="ns-chart__col" tabindex="0" style="--v:64%">
      <span class="ns-chart__tip">W4 · 64</span>
      <div class="ns-chart__bar"></div>
    </div>
    </div>
  </figure>
</div>

Grouped

Two series per band, separated by the 2px surface gap — never a stroke. Legend is mandatory from the second series on.

Course completions weekly · last 6 weeks
  • Admin track
  • Developer track
0255075100
W1 · admin 38 · dev 24
W2 · admin 52 · dev 30
W3 · admin 46 · dev 41
W4 · admin 64 · dev 38
W5 · admin 58 · dev 52
W6 · admin 82 · dev 61
W1W2W3W4W5W6
markup
<figure class="ns-chart">
  <div class="ns-chart__head">
    <span class="ns-chart__title">Course completions</span>
    <span class="ns-chart__sub">weekly · last 6 weeks</span>
  </div>
  <ul class="ns-chart__legend">
    <li class="ns-chart__key" data-c="1"><span class="ns-chart__swatch"></span>Admin track</li>
    <li class="ns-chart__key" data-c="2"><span class="ns-chart__swatch"></span>Developer track</li>
  </ul>
  <div class="ns-chart__frame">
    <div class="ns-chart__y"><span>0</span><span>25</span><span>50</span><span>75</span><span>100</span></div>
    <div class="ns-chart__plot">
      <div class="ns-chart__col ns-chart__col--group" tabindex="0">
        <span class="ns-chart__tip" style="--v:38%">W1 · admin 38 · dev 24</span>
        <div class="ns-chart__bar" data-c="1" style="--v:38%"></div>
        <div class="ns-chart__bar" data-c="2" style="--v:24%"></div>
      </div>
      <div class="ns-chart__col ns-chart__col--group" tabindex="0">
        <span class="ns-chart__tip" style="--v:52%">W2 · admin 52 · dev 30</span>
        <div class="ns-chart__bar" data-c="1" style="--v:52%"></div>
        <div class="ns-chart__bar" data-c="2" style="--v:30%"></div>
      </div>
      <div class="ns-chart__col ns-chart__col--group" tabindex="0">
        <span class="ns-chart__tip" style="--v:46%">W3 · admin 46 · dev 41</span>
        <div class="ns-chart__bar" data-c="1" style="--v:46%"></div>
        <div class="ns-chart__bar" data-c="2" style="--v:41%"></div>
      </div>
      <div class="ns-chart__col ns-chart__col--group" tabindex="0">
        <span class="ns-chart__tip" style="--v:64%">W4 · admin 64 · dev 38</span>
        <div class="ns-chart__bar" data-c="1" style="--v:64%"></div>
        <div class="ns-chart__bar" data-c="2" style="--v:38%"></div>
      </div>
      <div class="ns-chart__col ns-chart__col--group" tabindex="0">
        <span class="ns-chart__tip" style="--v:58%">W5 · admin 58 · dev 52</span>
        <div class="ns-chart__bar" data-c="1" style="--v:58%"></div>
        <div class="ns-chart__bar" data-c="2" style="--v:52%"></div>
      </div>
      <div class="ns-chart__col ns-chart__col--group" tabindex="0">
        <span class="ns-chart__tip" style="--v:82%">W6 · admin 82 · dev 61</span>
        <div class="ns-chart__bar" data-c="1" style="--v:82%"></div>
        <div class="ns-chart__bar" data-c="2" style="--v:61%"></div>
      </div>
    </div>
  <div class="ns-chart__x"><span>W1</span><span>W2</span><span>W3</span><span>W4</span><span>W5</span><span>W6</span></div>
  </div>
</figure>

Stacked

Parts of a whole over time. Segments stack bottom-up in slot order with the surface gap between them; only the top segment gets the rounded end.

Lessons completed by typeweekly
  • Video
  • Reading
  • Lab
W1 · 60 total
W2 · 68 total
W3 · 62 total
W4 · 78 total
W1W2W3W4
markup
<figure class="ns-chart">
  <div class="ns-chart__head"><span class="ns-chart__title">Lessons completed by type</span><span class="ns-chart__sub">weekly</span></div>
  <ul class="ns-chart__legend">
    <li class="ns-chart__key" data-c="1"><span class="ns-chart__swatch"></span>Video</li>
    <li class="ns-chart__key" data-c="2"><span class="ns-chart__swatch"></span>Reading</li>
    <li class="ns-chart__key" data-c="3"><span class="ns-chart__swatch"></span>Lab</li>
  </ul>
  <div class="ns-chart__plot">
    <div class="ns-chart__col" tabindex="0">
      <span class="ns-chart__tip" style="--v:60%">W1 · 60 total</span>
      <div class="ns-chart__stack">
        <div class="ns-chart__seg" data-c="1" style="--v:30%"></div>
        <div class="ns-chart__seg" data-c="2" style="--v:18%"></div>
        <div class="ns-chart__seg" data-c="3" style="--v:12%"></div>
      </div>
    </div>
    <div class="ns-chart__col" tabindex="0">
      <span class="ns-chart__tip" style="--v:68%">W2 · 68 total</span>
      <div class="ns-chart__stack">
        <div class="ns-chart__seg" data-c="1" style="--v:36%"></div>
        <div class="ns-chart__seg" data-c="2" style="--v:22%"></div>
        <div class="ns-chart__seg" data-c="3" style="--v:10%"></div>
      </div>
    </div>
    <div class="ns-chart__col" tabindex="0">
      <span class="ns-chart__tip" style="--v:62%">W3 · 62 total</span>
      <div class="ns-chart__stack">
        <div class="ns-chart__seg" data-c="1" style="--v:28%"></div>
        <div class="ns-chart__seg" data-c="2" style="--v:16%"></div>
        <div class="ns-chart__seg" data-c="3" style="--v:18%"></div>
      </div>
    </div>
    <div class="ns-chart__col" tabindex="0">
      <span class="ns-chart__tip" style="--v:78%">W4 · 78 total</span>
      <div class="ns-chart__stack">
        <div class="ns-chart__seg" data-c="1" style="--v:44%"></div>
        <div class="ns-chart__seg" data-c="2" style="--v:20%"></div>
        <div class="ns-chart__seg" data-c="3" style="--v:14%"></div>
      </div>
    </div>
  </div>
  <div class="ns-chart__x"><span>W1</span><span>W2</span><span>W3</span><span>W4</span></div>
</figure>

Horizontal

For ranked entities with real names — the label column keeps them readable. Bars slide in from the left; hover a row for its tooltip.

Enrollments by coursethis quarter
Apex basics · 460 Apex basics
460
Admin cert · 371 Admin cert
371
Flows · 290 Flows
290
LWC · 205 LWC
205
SOQL · 131 SOQL
131
markup
<figure class="ns-chart">
  <div class="ns-chart__head"><span class="ns-chart__title">Enrollments by course</span><span class="ns-chart__sub">this quarter</span></div>
  <div class="ns-chart__rows">
    <div class="ns-chart__row" tabindex="0">
      <span class="ns-chart__tip" style="--v:92%">Apex basics · 460</span>
      <span class="ns-chart__row-label">Apex basics</span>
      <div><div class="ns-chart__hbar" data-c="1" style="--v:92%"></div></div>
      <span class="ns-chart__row-value">460</span>
    </div>
    <div class="ns-chart__row" tabindex="0">
      <span class="ns-chart__tip" style="--v:74%">Admin cert · 371</span>
      <span class="ns-chart__row-label">Admin cert</span>
      <div><div class="ns-chart__hbar" data-c="1" style="--v:74%"></div></div>
      <span class="ns-chart__row-value">371</span>
    </div>
    <div class="ns-chart__row" tabindex="0">
      <span class="ns-chart__tip" style="--v:58%">Flows · 290</span>
      <span class="ns-chart__row-label">Flows</span>
      <div><div class="ns-chart__hbar" data-c="1" style="--v:58%"></div></div>
      <span class="ns-chart__row-value">290</span>
    </div>
    <div class="ns-chart__row" tabindex="0">
      <span class="ns-chart__tip" style="--v:41%">LWC · 205</span>
      <span class="ns-chart__row-label">LWC</span>
      <div><div class="ns-chart__hbar" data-c="1" style="--v:41%"></div></div>
      <span class="ns-chart__row-value">205</span>
    </div>
    <div class="ns-chart__row" tabindex="0">
      <span class="ns-chart__tip" style="--v:26%">SOQL · 131</span>
      <span class="ns-chart__row-label">SOQL</span>
      <div><div class="ns-chart__hbar" data-c="1" style="--v:26%"></div></div>
      <span class="ns-chart__row-value">131</span>
    </div>
  </div>
</figure>

Diverging

Above/below a baseline — cool arm up, warm arm down, from the diverging ramp. Never status red/green: polarity is not health.

Enrollment change vs last monthby course
Apex basics · +32% Apex basics
+32%
Flows · +19% Flows
+19%
Admin cert · −11% Admin cert
−11%
SOQL · −23% SOQL
−23%
markup
<figure class="ns-chart">
  <div class="ns-chart__head"><span class="ns-chart__title">Enrollment change vs last month</span><span class="ns-chart__sub">by course</span></div>
  <div class="ns-chart__rows">
    <div class="ns-chart__row" tabindex="0">
      <span class="ns-chart__tip" style="--v:64%">Apex basics · +32%</span>
      <span class="ns-chart__row-label">Apex basics</span>
      <div><div class="ns-chart__hbar" data-pole="up" style="--v:64%"></div></div>
      <span class="ns-chart__row-value">+32%</span>
    </div>
    <div class="ns-chart__row" tabindex="0">
      <span class="ns-chart__tip" style="--v:38%">Flows · +19%</span>
      <span class="ns-chart__row-label">Flows</span>
      <div><div class="ns-chart__hbar" data-pole="up" style="--v:38%"></div></div>
      <span class="ns-chart__row-value">+19%</span>
    </div>
    <div class="ns-chart__row" tabindex="0">
      <span class="ns-chart__tip" style="--v:22%">Admin cert · −11%</span>
      <span class="ns-chart__row-label">Admin cert</span>
      <div><div class="ns-chart__hbar" data-pole="down" style="--v:22%"></div></div>
      <span class="ns-chart__row-value">−11%</span>
    </div>
    <div class="ns-chart__row" tabindex="0">
      <span class="ns-chart__tip" style="--v:46%">SOQL · −23%</span>
      <span class="ns-chart__row-label">SOQL</span>
      <div><div class="ns-chart__hbar" data-pole="down" style="--v:46%"></div></div>
      <span class="ns-chart__row-value">−23%</span>
    </div>
  </div>
</figure>

With trend line

A 2px line over the columns carries the trend; vector-effect keeps it 2px at any width. The line draws itself on load.

Completions + 3-week trendweekly
  • Completions
  • Trend
W1 · 38
W2 · 52
W3 · 46
W4 · 64
W5 · 58
W6 · 82
W1W2W3W4W5W6
markup
<figure class="ns-chart">
  <div class="ns-chart__head"><span class="ns-chart__title">Completions + 3-week trend</span><span class="ns-chart__sub">weekly</span></div>
  <ul class="ns-chart__legend">
    <li class="ns-chart__key" data-c="1"><span class="ns-chart__swatch"></span>Completions</li>
    <li class="ns-chart__key" data-c="2"><span class="ns-chart__swatch ns-chart__swatch--line"></span>Trend</li>
  </ul>
  <div class="ns-chart__plot">
    <div class="ns-chart__col" tabindex="0" style="--v:38%">
      <span class="ns-chart__tip">W1 · 38</span>
      <div class="ns-chart__bar"></div>
    </div>
    <div class="ns-chart__col" tabindex="0" style="--v:52%">
      <span class="ns-chart__tip">W2 · 52</span>
      <div class="ns-chart__bar"></div>
    </div>
    <div class="ns-chart__col" tabindex="0" style="--v:46%">
      <span class="ns-chart__tip">W3 · 46</span>
      <div class="ns-chart__bar"></div>
    </div>
    <div class="ns-chart__col" tabindex="0" style="--v:64%">
      <span class="ns-chart__tip">W4 · 64</span>
      <div class="ns-chart__bar"></div>
    </div>
    <div class="ns-chart__col" tabindex="0" style="--v:58%">
      <span class="ns-chart__tip">W5 · 58</span>
      <div class="ns-chart__bar"></div>
    </div>
    <div class="ns-chart__col" tabindex="0" style="--v:82%">
      <span class="ns-chart__tip">W6 · 82</span>
      <div class="ns-chart__bar"></div>
    </div>
    <svg class="ns-chart__svg" viewBox="0 0 100 100" preserveAspectRatio="none" aria-hidden="true" style="position:absolute;inset:0;block-size:100%">
      <polyline class="ns-chart__line ns-chart__line--draw" data-c="2" vector-effect="non-scaling-stroke" pathLength="1" points="8,60 25,50 41,53 58,40 75,44 92,22"/>
    </svg>
  </div>
  <div class="ns-chart__x"><span>W1</span><span>W2</span><span>W3</span><span>W4</span><span>W5</span><span>W6</span></div>
</figure>