Open demo

CSS code

HTML
<div><span class="lbl">Stacked storage</span><div class="card">
<div class="sg">
  <div class="sg-head"><b>Storage</b><span><strong>74 GB</strong> of 100 GB used</span></div>
  <div class="sg-stack" aria-hidden="true"><i style="--v:38;--c:#6d28d9"></i><i style="--v:22;--c:#0369a1"></i><i style="--v:9;--c:#c2410c"></i><i style="--v:5;--c:#be185d"></i></div>
  <ul class="sg-legend">
    <li style="--c:#6d28d9">Photos <b>38 GB</b></li>
    <li style="--c:#0369a1">Videos <b>22 GB</b></li>
    <li style="--c:#c2410c">Documents <b>9 GB</b></li>
    <li style="--c:#be185d">Apps <b>5 GB</b></li>
  </ul>
</div></div></div>

<div><span class="lbl">Quota with native meter</span><div class="card">
<div class="sg">
  <div class="sg-head"><label for="sg-seats">Team seats</label><span><strong>12</strong> of 25 · <em class="sg-state ok">Plenty left</em></span></div>
  <meter id="sg-seats" min="0" max="25" low="18" high="23" optimum="0" value="12">12 of 25</meter>
</div>
<div class="sg">
  <div class="sg-head"><label for="sg-files">File storage</label><span><strong>82 GB</strong> of 100 GB · <em class="sg-state warn">Running low</em></span></div>
  <meter id="sg-files" min="0" max="100" low="70" high="90" optimum="0" value="82">82 GB of 100 GB</meter>
</div>
<div class="sg">
  <div class="sg-head"><label for="sg-api">API calls this month</label><span><strong>9,640</strong> of 10,000 · <em class="sg-state bad">Almost out</em></span></div>
  <meter id="sg-api" min="0" max="10000" low="7000" high="9000" optimum="0" value="9640">9,640 of 10,000</meter>
</div></div></div>

<div><span class="lbl">Segmented count</span><div class="card">
<div class="sg">
  <div class="sg-head"><b id="sg-setup">Workspace setup</b><span><strong>3</strong> of 5 tasks done</span></div>
  <div class="sg-steps" role="progressbar" aria-labelledby="sg-setup" aria-valuenow="3" aria-valuemin="0" aria-valuemax="5" aria-valuetext="3 of 5 tasks done" style="--n:5">
    <i class="on"></i><i class="on"></i><i class="on"></i><i></i><i></i>
  </div>
  <p class="sg-note">Next: connect your domain</p>
</div>
<div class="sg">
  <div class="sg-head"><b id="sg-streak">Weekly workout goal</b><span><strong>4</strong> of 7 days</span></div>
  <div class="sg-steps" role="progressbar" aria-labelledby="sg-streak" aria-valuenow="4" aria-valuemin="0" aria-valuemax="7" aria-valuetext="4 of 7 days" style="--n:7;--sg-accent:#0369a1">
    <i class="on"></i><i class="on"></i><i class="on"></i><i class="on"></i><i></i><i></i><i></i>
  </div>
</div></div></div>
CSS
/* Stacked, quota and segmented bars.
   Stacked: the coloured bar is decorative (aria-hidden); the used total and the legend carry the numbers as text.
   Quota: a native <meter> with low/high/optimum, so the browser picks the colour band and exposes the value.
   Segmented: role="progressbar" with a whole-number value over a row of blocks. */
.sg{--sg-track:#e4e3ee;--sg-accent:#6d28d9;display:grid;gap:10px}
.sg+.sg{margin-top:20px}
.sg-head{display:flex;flex-wrap:wrap;justify-content:space-between;align-items:baseline;gap:4px 12px;font-size:.92rem}
.sg-head b,.sg-head label{font-weight:600;color:#1f1d38}
.sg-head span{font-size:.86rem;color:#4b4966;font-variant-numeric:tabular-nums}
.sg-head span strong{color:#1f1d38}
/* stacked: each segment's width is its share (--v, 0 to 100); a white gap separates them */
.sg-stack{display:flex;height:12px;border-radius:999px;background:var(--sg-track);overflow:hidden}
.sg-stack>i{width:calc(var(--v) * 1%);background:var(--c);border-right:2px solid #fff}
.sg-legend{display:flex;flex-wrap:wrap;gap:8px 16px;list-style:none;font-size:.84rem;color:#4b4966}
.sg-legend li{display:flex;align-items:center;gap:7px}
.sg-legend li::before{content:"";width:10px;height:10px;border-radius:3px;background:var(--c)}
.sg-legend b{color:#1f1d38;font-weight:600;font-variant-numeric:tabular-nums}
/* quota: native <meter>; WebKit/Blink and Firefox each need their own pseudo-elements */
.sg meter{--ok:#15803d;--warn:#b45309;--bad:#dc2626;-webkit-appearance:none;appearance:none;display:block;width:100%;height:10px;
  border:0;border-radius:999px;background:var(--sg-track);overflow:hidden}
.sg meter::-webkit-meter-bar{height:10px;border:0;border-radius:999px;background:var(--sg-track)}
.sg meter::-webkit-meter-optimum-value{border-radius:999px;background:var(--ok)}
.sg meter::-webkit-meter-suboptimum-value{border-radius:999px;background:var(--warn)}
.sg meter::-webkit-meter-even-less-good-value{border-radius:999px;background:var(--bad)}
.sg meter::-moz-meter-bar{border-radius:999px;background:var(--ok)}
.sg meter:-moz-meter-sub-optimum::-moz-meter-bar{background:var(--warn)}
.sg meter:-moz-meter-sub-sub-optimum::-moz-meter-bar{background:var(--bad)}
.sg-state{font-size:.8rem;font-weight:700;font-style:normal}
.sg-state.ok{color:#15803d}.sg-state.warn{color:#b45309}.sg-state.bad{color:#dc2626}
/* segmented: one block per unit */
.sg-steps{display:grid;grid-template-columns:repeat(var(--n),1fr);gap:6px}
.sg-steps>i{height:10px;border-radius:5px;background:var(--sg-track)}
.sg-steps>i.on{background:var(--sg-accent)}
.sg-note{font-size:.84rem;color:#4b4966}

Bootstrap 5 code

Requires: Bootstrap 5.3.8 CSS

HTML
<div><span class="lbl">Stacked storage</span><div class="card demo-card"><div class="card-body p-4">
<div class="sg">
  <div class="d-flex flex-wrap justify-content-between align-items-baseline column-gap-3 row-gap-1"><span class="fw-semibold">Storage</span><span class="sg-meta"><strong>74 GB</strong> of 100 GB used</span></div>
  <div class="progress-stacked" aria-hidden="true">
    <div class="progress" style="width:38%;--c:#6d28d9"><div class="progress-bar"></div></div>
    <div class="progress" style="width:22%;--c:#0369a1"><div class="progress-bar"></div></div>
    <div class="progress" style="width:9%;--c:#c2410c"><div class="progress-bar"></div></div>
    <div class="progress" style="width:5%;--c:#be185d"><div class="progress-bar"></div></div>
  </div>
  <ul class="sg-legend list-unstyled d-flex flex-wrap row-gap-2 column-gap-3 mb-0">
    <li style="--c:#6d28d9">Photos <b>38 GB</b></li>
    <li style="--c:#0369a1">Videos <b>22 GB</b></li>
    <li style="--c:#c2410c">Documents <b>9 GB</b></li>
    <li style="--c:#be185d">Apps <b>5 GB</b></li>
  </ul>
</div></div></div></div>

<div><span class="lbl">Quota with native meter</span><div class="card demo-card"><div class="card-body p-4">
<div class="sg">
  <div class="d-flex flex-wrap justify-content-between align-items-baseline column-gap-3 row-gap-1"><label class="fw-semibold" for="sg-seats">Team seats</label><span class="sg-meta"><strong>12</strong> of 25 · <em class="sg-state fw-bold text-success">Plenty left</em></span></div>
  <meter id="sg-seats" min="0" max="25" low="18" high="23" optimum="0" value="12">12 of 25</meter>
</div>
<div class="sg">
  <div class="d-flex flex-wrap justify-content-between align-items-baseline column-gap-3 row-gap-1"><label class="fw-semibold" for="sg-files">File storage</label><span class="sg-meta"><strong>82 GB</strong> of 100 GB · <em class="sg-state fw-bold text-warning">Running low</em></span></div>
  <meter id="sg-files" min="0" max="100" low="70" high="90" optimum="0" value="82">82 GB of 100 GB</meter>
</div>
<div class="sg">
  <div class="d-flex flex-wrap justify-content-between align-items-baseline column-gap-3 row-gap-1"><label class="fw-semibold" for="sg-api">API calls this month</label><span class="sg-meta"><strong>9,640</strong> of 10,000 · <em class="sg-state fw-bold text-danger">Almost out</em></span></div>
  <meter id="sg-api" min="0" max="10000" low="7000" high="9000" optimum="0" value="9640">9,640 of 10,000</meter>
</div></div></div></div>

<div><span class="lbl">Segmented count</span><div class="card demo-card"><div class="card-body p-4">
<div class="sg">
  <div class="d-flex flex-wrap justify-content-between align-items-baseline column-gap-3 row-gap-1"><span class="fw-semibold" id="sg-setup">Workspace setup</span><span class="sg-meta"><strong>3</strong> of 5 tasks done</span></div>
  <div class="sg-steps d-flex" role="progressbar" aria-labelledby="sg-setup" aria-valuenow="3" aria-valuemin="0" aria-valuemax="5" aria-valuetext="3 of 5 tasks done">
    <div class="progress flex-fill"><div class="progress-bar w-100"></div></div><div class="progress flex-fill"><div class="progress-bar w-100"></div></div><div class="progress flex-fill"><div class="progress-bar w-100"></div></div><div class="progress flex-fill"></div><div class="progress flex-fill"></div>
  </div>
  <p class="sg-note mb-0">Next: connect your domain</p>
</div>
<div class="sg">
  <div class="d-flex flex-wrap justify-content-between align-items-baseline column-gap-3 row-gap-1"><span class="fw-semibold" id="sg-streak">Weekly workout goal</span><span class="sg-meta"><strong>4</strong> of 7 days</span></div>
  <div class="sg-steps sky d-flex" role="progressbar" aria-labelledby="sg-streak" aria-valuenow="4" aria-valuemin="0" aria-valuemax="7" aria-valuetext="4 of 7 days">
    <div class="progress flex-fill"><div class="progress-bar w-100"></div></div><div class="progress flex-fill"><div class="progress-bar w-100"></div></div><div class="progress flex-fill"><div class="progress-bar w-100"></div></div><div class="progress flex-fill"><div class="progress-bar w-100"></div></div><div class="progress flex-fill"></div><div class="progress flex-fill"></div><div class="progress flex-fill"></div>
  </div>
</div></div></div></div>
CSS
/* Stacked: Bootstrap .progress-stacked, decorative here (aria-hidden) because the total and the legend carry the numbers.
   Quota: a native <meter> (Bootstrap has no meter styles), coloured by its low/high/optimum band.
   Segmented: a row of .progress blocks inside one role="progressbar". */
.sg{--sg-track:#e4e3ee;display:grid;gap:10px;font-size:.92rem}
.sg+.sg{margin-top:20px}
.sg .sg-meta{font-size:.86rem;color:#4b4966;font-variant-numeric:tabular-nums}
.sg .sg-meta strong{color:#1f1d38}
.sg .progress,.sg .progress-stacked{--bs-progress-bg:var(--sg-track);--bs-progress-border-radius:999px}
.sg .progress-stacked{--bs-progress-height:12px}
.sg .progress-stacked>.progress{border-right:2px solid #fff}
.sg .progress-stacked .progress-bar{background:var(--c)}
.sg .sg-legend{font-size:.84rem;color:#4b4966}
.sg .sg-legend li{display:flex;align-items:center;gap:7px}
.sg .sg-legend li::before{content:"";width:10px;height:10px;border-radius:3px;background:var(--c)}
.sg .sg-legend b{color:#1f1d38;font-weight:600;font-variant-numeric:tabular-nums}
/* quota: native <meter>; WebKit/Blink and Firefox each need their own pseudo-elements */
.sg meter{--ok:#15803d;--warn:#b45309;--bad:#dc2626;-webkit-appearance:none;appearance:none;display:block;width:100%;height:10px;
  border:0;border-radius:999px;background:var(--sg-track);overflow:hidden}
.sg meter::-webkit-meter-bar{height:10px;border:0;border-radius:999px;background:var(--sg-track)}
.sg meter::-webkit-meter-optimum-value{border-radius:999px;background:var(--ok)}
.sg meter::-webkit-meter-suboptimum-value{border-radius:999px;background:var(--warn)}
.sg meter::-webkit-meter-even-less-good-value{border-radius:999px;background:var(--bad)}
.sg meter::-moz-meter-bar{border-radius:999px;background:var(--ok)}
.sg meter:-moz-meter-sub-optimum::-moz-meter-bar{background:var(--warn)}
.sg meter:-moz-meter-sub-sub-optimum::-moz-meter-bar{background:var(--bad)}
.sg .sg-state{font-size:.8rem;font-style:normal}
.sg{--bs-success-rgb:21,128,61;--bs-warning-rgb:180,83,9;--bs-danger-rgb:220,38,38}
/* segmented: one .progress block per unit */
.sg .sg-steps{gap:6px}
.sg .sg-steps .progress{--bs-progress-height:10px;--bs-progress-bar-bg:#6d28d9;--bs-progress-border-radius:5px}
.sg .sg-steps.sky .progress{--bs-progress-bar-bg:#0369a1}
.sg .sg-note{font-size:.84rem;color:#4b4966}

Tailwind 4 code

Requires: Tailwind CSS 4

HTML
<div><span class="mb-3 block text-[.72rem] tracking-[.12em] text-[#5c5a74] uppercase">Stacked storage</span><div class="rounded-2xl border border-[#e4e3ee] bg-white px-6 pt-[22px] pb-6 shadow-[0_1px_2px_rgba(31,29,56,.04)]">
<div class="grid gap-2.5 text-[.92rem]">
  <div class="flex flex-wrap items-baseline justify-between gap-x-3 gap-y-1"><span class="font-semibold">Storage</span><span class="text-[.86rem] text-[#4b4966] tabular-nums"><strong class="text-[#1f1d38]">74 GB</strong> of 100 GB used</span></div>
  <div class="flex h-3 overflow-hidden rounded-full bg-sg-track" aria-hidden="true"><i class="w-[38%] border-r-2 border-white bg-sg-violet"></i><i class="w-[22%] border-r-2 border-white bg-sg-sky"></i><i class="w-[9%] border-r-2 border-white bg-sg-orange"></i><i class="w-[5%] border-r-2 border-white bg-sg-pink"></i></div>
  <ul class="flex flex-wrap gap-x-4 gap-y-2 text-[.84rem] text-[#4b4966]">
    <li class="flex items-center gap-[7px] before:size-2.5 before:rounded-[3px] before:bg-sg-violet before:content-['']">Photos <b class="font-semibold text-[#1f1d38] tabular-nums">38 GB</b></li>
    <li class="flex items-center gap-[7px] before:size-2.5 before:rounded-[3px] before:bg-sg-sky before:content-['']">Videos <b class="font-semibold text-[#1f1d38] tabular-nums">22 GB</b></li>
    <li class="flex items-center gap-[7px] before:size-2.5 before:rounded-[3px] before:bg-sg-orange before:content-['']">Documents <b class="font-semibold text-[#1f1d38] tabular-nums">9 GB</b></li>
    <li class="flex items-center gap-[7px] before:size-2.5 before:rounded-[3px] before:bg-sg-pink before:content-['']">Apps <b class="font-semibold text-[#1f1d38] tabular-nums">5 GB</b></li>
  </ul>
</div></div></div>

<div><span class="mb-3 block text-[.72rem] tracking-[.12em] text-[#5c5a74] uppercase">Quota with native meter</span><div class="rounded-2xl border border-[#e4e3ee] bg-white px-6 pt-[22px] pb-6 shadow-[0_1px_2px_rgba(31,29,56,.04)]">
<div class="grid gap-2.5 text-[.92rem]">
  <div class="flex flex-wrap items-baseline justify-between gap-x-3 gap-y-1"><label class="font-semibold" for="sg-seats">Team seats</label><span class="text-[.86rem] text-[#4b4966] tabular-nums"><strong class="text-[#1f1d38]">12</strong> of 25 · <em class="text-[.8rem] font-bold text-sg-ok not-italic">Plenty left</em></span></div>
  <meter class="sg-meter" id="sg-seats" min="0" max="25" low="18" high="23" optimum="0" value="12">12 of 25</meter>
</div>
<div class="mt-5 grid gap-2.5 text-[.92rem]">
  <div class="flex flex-wrap items-baseline justify-between gap-x-3 gap-y-1"><label class="font-semibold" for="sg-files">File storage</label><span class="text-[.86rem] text-[#4b4966] tabular-nums"><strong class="text-[#1f1d38]">82 GB</strong> of 100 GB · <em class="text-[.8rem] font-bold text-sg-warn not-italic">Running low</em></span></div>
  <meter class="sg-meter" id="sg-files" min="0" max="100" low="70" high="90" optimum="0" value="82">82 GB of 100 GB</meter>
</div>
<div class="mt-5 grid gap-2.5 text-[.92rem]">
  <div class="flex flex-wrap items-baseline justify-between gap-x-3 gap-y-1"><label class="font-semibold" for="sg-api">API calls this month</label><span class="text-[.86rem] text-[#4b4966] tabular-nums"><strong class="text-[#1f1d38]">9,640</strong> of 10,000 · <em class="text-[.8rem] font-bold text-sg-bad not-italic">Almost out</em></span></div>
  <meter class="sg-meter" id="sg-api" min="0" max="10000" low="7000" high="9000" optimum="0" value="9640">9,640 of 10,000</meter>
</div></div></div>

<div><span class="mb-3 block text-[.72rem] tracking-[.12em] text-[#5c5a74] uppercase">Segmented count</span><div class="rounded-2xl border border-[#e4e3ee] bg-white px-6 pt-[22px] pb-6 shadow-[0_1px_2px_rgba(31,29,56,.04)]">
<div class="grid gap-2.5 text-[.92rem]">
  <div class="flex flex-wrap items-baseline justify-between gap-x-3 gap-y-1"><span class="font-semibold" id="sg-setup">Workspace setup</span><span class="text-[.86rem] text-[#4b4966] tabular-nums"><strong class="text-[#1f1d38]">3</strong> of 5 tasks done</span></div>
  <div class="grid grid-cols-5 gap-1.5" role="progressbar" aria-labelledby="sg-setup" aria-valuenow="3" aria-valuemin="0" aria-valuemax="5" aria-valuetext="3 of 5 tasks done">
    <i class="h-2.5 rounded-[5px] bg-sg-violet"></i><i class="h-2.5 rounded-[5px] bg-sg-violet"></i><i class="h-2.5 rounded-[5px] bg-sg-violet"></i><i class="h-2.5 rounded-[5px] bg-sg-track"></i><i class="h-2.5 rounded-[5px] bg-sg-track"></i>
  </div>
  <p class="text-[.84rem] text-[#4b4966]">Next: connect your domain</p>
</div>
<div class="mt-5 grid gap-2.5 text-[.92rem]">
  <div class="flex flex-wrap items-baseline justify-between gap-x-3 gap-y-1"><span class="font-semibold" id="sg-streak">Weekly workout goal</span><span class="text-[.86rem] text-[#4b4966] tabular-nums"><strong class="text-[#1f1d38]">4</strong> of 7 days</span></div>
  <div class="grid grid-cols-7 gap-1.5" role="progressbar" aria-labelledby="sg-streak" aria-valuenow="4" aria-valuemin="0" aria-valuemax="7" aria-valuetext="4 of 7 days">
    <i class="h-2.5 rounded-[5px] bg-sg-sky"></i><i class="h-2.5 rounded-[5px] bg-sg-sky"></i><i class="h-2.5 rounded-[5px] bg-sg-sky"></i><i class="h-2.5 rounded-[5px] bg-sg-sky"></i><i class="h-2.5 rounded-[5px] bg-sg-track"></i><i class="h-2.5 rounded-[5px] bg-sg-track"></i><i class="h-2.5 rounded-[5px] bg-sg-track"></i>
  </div>
</div></div></div>
CSS
@theme {
  --color-sg-track: #e4e3ee;
  --color-sg-violet: #6d28d9;
  --color-sg-sky: #0369a1;
  --color-sg-orange: #c2410c;
  --color-sg-pink: #be185d;
  --color-sg-ok: #15803d;
  --color-sg-warn: #b45309;
  --color-sg-bad: #dc2626;
}
/* Native <meter>: WebKit/Blink and Firefox each need their own pseudo-elements, so the shared styles live here. */
@utility sg-meter {
  -webkit-appearance: none; appearance: none; display: block; width: 100%; height: 10px; border: 0;
  border-radius: 999px; background: var(--color-sg-track); overflow: hidden;
  &::-webkit-meter-bar { height: 10px; border: 0; border-radius: 999px; background: var(--color-sg-track); }
  &::-webkit-meter-optimum-value { border-radius: 999px; background: var(--color-sg-ok); }
  &::-webkit-meter-suboptimum-value { border-radius: 999px; background: var(--color-sg-warn); }
  &::-webkit-meter-even-less-good-value { border-radius: 999px; background: var(--color-sg-bad); }
  &::-moz-meter-bar { border-radius: 999px; background: var(--color-sg-ok); }
  &:-moz-meter-sub-optimum::-moz-meter-bar { background: var(--color-sg-warn); }
  &:-moz-meter-sub-sub-optimum::-moz-meter-bar { background: var(--color-sg-bad); }
}

About this set

Bars that show more than one value, or show a value as a count of blocks. Stacked storage splits 74 GB of 100 GB into photos, videos, documents and apps, with a 2 pixel white gap between the coloured segments and a legend underneath; the coloured bar is decorative and the total and the legend carry the numbers as text. Quota with native meter uses the meter element, which is the right one for a measurement inside a known range such as seats, storage or API calls. Its low, high and optimum attributes let the browser pick the band, so the same CSS paints 12 of 25 seats green, 82 GB of 100 amber and 9,640 of 10,000 API calls red, and the status is also written out in words. Segmented count draws one block per unit, for 3 of 5 setup tasks or 4 of 7 workout days, inside a single role=”progressbar” with the count in aria-valuetext. The meter is styled through ::-webkit-meter-bar and its three value pseudo-elements for Chrome, Edge and Safari, and ::-moz-meter-bar with the sub-optimum pseudo-classes for Firefox.

What’s included

  • Stacked storage bar with a legend
  • Native meter that changes colour from its low, high and optimum attributes
  • Meter styled for WebKit, Blink and Firefox
  • Segmented block count for tasks and streaks
  • Status written in words as well as colour
  • Bootstrap version uses .progress-stacked for the storage bar

Accessibility

The quota meters are native meter elements labelled with label for, so screen readers announce them with their value. The segmented counts are role="progressbar" elements with aria-valuetext such as 3 of 5 tasks done. The stacked storage bar is marked aria-hidden because its heading and legend already give every number as text. Colour is never the only signal: each quota has a status word next to it.

Customise it

Change --sg-track and --sg-accent on .sg, the --c colour on each stacked segment, and --ok, --warn and --bad on the meter in the plain CSS and Bootstrap versions; the meter bands come from its low, high and optimum attributes. In Tailwind edit the sg- theme colours and the sg-meter utility.