Open demo

CSS code

HTML
<div><span class="lbl">Neon gradient</span><div class="card">
<div class="dk neon">
  <div class="dk-head"><b id="dk-deploy">Deploying api-gateway to production</b><span aria-hidden="true">76%</span></div>
  <div class="dk-bar" role="progressbar" aria-labelledby="dk-deploy" aria-valuenow="76" aria-valuemin="0" aria-valuemax="100" aria-valuetext="76%, step 4 of 5, running health checks" style="--v:76"><i></i></div>
  <p class="dk-note">Step 4 of 5 · Running health checks on 12 pods</p>
</div></div></div>

<div><span class="lbl">Battery cells</span><div class="card">
<div class="dk batt">
  <div class="dk-head"><b id="dk-batt">Charging</b><span aria-hidden="true">60%</span></div>
  <div class="dk-batt">
    <div class="dk-cells" role="progressbar" aria-labelledby="dk-batt" aria-valuenow="60" aria-valuemin="0" aria-valuemax="100" aria-valuetext="60%, 48 minutes to full">
      <i class="on"></i><i class="on"></i><i class="on"></i><i class="on"></i><i class="on"></i><i class="on"></i><i class="next"></i><i></i><i></i><i></i>
    </div>
  </div>
  <p class="dk-note">48 minutes to full · Fast charging</p>
</div></div></div>

<div><span class="lbl">Glow ring</span><div class="card">
<div class="dk ring">
  <div class="dk-ring" role="progressbar" aria-labelledby="dk-sync" aria-valuenow="70" aria-valuemin="0" aria-valuemax="100" aria-valuetext="70%, 1,204 of 1,720 photos" style="--v:70"><span aria-hidden="true"></span><b aria-hidden="true">70%</b></div>
  <div class="dk-ring-txt"><b id="dk-sync">Syncing photo library</b><p><strong>1,204</strong> of 1,720 photos</p><p>About 6 minutes left on Wi-Fi</p></div>
</div></div></div>

<div><span class="lbl">Level and XP</span><div class="card">
<div class="dk level">
  <div class="dk-head"><b id="dk-xp">Level progress</b><span aria-hidden="true">2,340 / 3,000 XP</span></div>
  <div class="dk-xp">
    <span class="dk-lvl" aria-hidden="true">12</span>
    <div class="dk-bar" role="progressbar" aria-labelledby="dk-xp" aria-valuenow="2340" aria-valuemin="0" aria-valuemax="3000" aria-valuetext="Level 12, 2,340 of 3,000 XP to level 13" style="--v:78"><i></i></div>
    <span class="dk-lvl next" aria-hidden="true">13</span>
  </div>
  <p class="dk-note">660 XP to level 13 · Finish two more lessons today</p>
</div></div></div>
CSS
/* Dark progress bars. role="progressbar" with aria-value* on each bar; --v (0 to 100) sets the fill.
   The sheen, the charging pulse and every other loop stop under prefers-reduced-motion. */
.dk{--dk-track:#26304a;--dk-ink:#e5e9f2;--dk-muted:#98a3bb;color:var(--dk-ink)}
.dk-head{display:flex;flex-wrap:wrap;justify-content:space-between;align-items:baseline;gap:4px 12px;font-size:.92rem}
.dk-head b{font-weight:600}
.dk-head span{font-weight:700;font-variant-numeric:tabular-nums}
.dk-note{margin-top:10px;font-size:.82rem;color:var(--dk-muted)}
/* neon: a gradient fill with a glow and a sheen that sweeps across it */
.dk-bar{--v:0;position:relative;height:10px;margin-top:12px;border-radius:999px;background:var(--dk-track)}
.dk-bar>i{position:relative;display:block;height:100%;width:calc(var(--v) * 1%);border-radius:inherit;overflow:hidden;
  background:linear-gradient(90deg,#22d3ee,#a78bfa);box-shadow:0 0 14px rgba(34,211,238,.45),0 0 4px rgba(167,139,250,.6)}
.dk-bar>i::after{content:"";position:absolute;inset:0;transform:translateX(-100%);
  background:linear-gradient(90deg,transparent,rgba(255,255,255,.55),transparent);animation:dk-sheen 2.4s ease-in-out infinite}
@keyframes dk-sheen{60%,to{transform:translateX(100%)}}
.dk.neon .dk-head span{color:#67e8f9}
/* battery: ten LED cells; the next cell pulses while charging */
.dk-batt{display:flex;align-items:center;gap:4px;margin-top:12px}
.dk-cells{flex:1;display:grid;grid-template-columns:repeat(10,1fr);gap:4px;padding:4px;border:2px solid #4b587a;border-radius:9px}
.dk-cells i{height:22px;border-radius:3px;background:var(--dk-track)}
.dk-cells i.on{background:#a3e635;box-shadow:0 0 8px rgba(163,230,53,.55)}
.dk-cells i.next{background:#a3e635;animation:dk-pulse 1.4s ease-in-out infinite}
@keyframes dk-pulse{0%,100%{opacity:.25}50%{opacity:1}}
.dk-batt::after{content:"";width:5px;height:14px;border-radius:0 3px 3px 0;background:#4b587a}
.dk.batt .dk-head span{color:#bef264}
/* glow ring: the glow is a drop-shadow on the ring's wrapper so the mask does not clip it */
.dk.ring{display:flex;align-items:center;gap:22px}
.dk-ring{--v:0;position:relative;flex:none;display:grid;place-items:center;width:112px;height:112px}
.dk-ring>span{position:absolute;inset:0;filter:drop-shadow(0 0 6px rgba(244,114,182,.55))}
.dk-ring>span::before{content:"";position:absolute;inset:0;border-radius:50%;
  background:conic-gradient(#f472b6 calc(var(--v) * 1%),var(--dk-track) 0);
  -webkit-mask:radial-gradient(farthest-side,transparent calc(100% - 9px),#000 calc(100% - 8px));
  mask:radial-gradient(farthest-side,transparent calc(100% - 9px),#000 calc(100% - 8px))}
.dk-ring b{position:relative;font-size:1.5rem;font-variant-numeric:tabular-nums}
.dk-ring-txt b{display:block;font-size:1rem;font-weight:600}
.dk-ring-txt p{margin-top:4px;font-size:.84rem;color:var(--dk-muted);font-variant-numeric:tabular-nums}
.dk-ring-txt strong{color:#f9a8d4}
/* level: badges at both ends of the bar */
.dk-xp{display:flex;align-items:center;gap:12px;margin-top:12px}
.dk-lvl{flex:none;display:grid;place-items:center;width:38px;height:38px;border-radius:11px;font-size:.9rem;font-weight:800;
  background:linear-gradient(135deg,#fbbf24,#f472b6);color:#1a1020}
.dk-lvl.next{background:transparent;border:2px solid #4b587a;color:var(--dk-muted)}
.dk-xp .dk-bar{flex:1;margin-top:0;height:12px}
.dk-xp .dk-bar>i{background:linear-gradient(90deg,#fbbf24,#f472b6);box-shadow:0 0 12px rgba(244,114,182,.4)}
.dk.level .dk-head span{color:#fcd34d}
@media (prefers-reduced-motion:reduce){
  .dk-bar>i::after{animation:none;display:none}
  .dk-cells i.next{animation:none;opacity:.45}
}

Bootstrap 5 code

Requires: Bootstrap 5.3.8 CSS

HTML
<div><span class="lbl">Neon gradient</span><div class="card demo-card"><div class="card-body p-4">
<div class="dk neon">
  <div class="dk-head d-flex flex-wrap justify-content-between align-items-baseline column-gap-3 row-gap-1"><b class="fw-semibold" id="dk-deploy">Deploying api-gateway to production</b><span class="fw-bold dk-val" aria-hidden="true">76%</span></div>
  <div class="progress" role="progressbar" aria-labelledby="dk-deploy" aria-valuenow="76" aria-valuemin="0" aria-valuemax="100" aria-valuetext="76%, step 4 of 5, running health checks"><div class="progress-bar" style="width:76%"></div></div>
  <p class="dk-note mb-0">Step 4 of 5 · Running health checks on 12 pods</p>
</div></div></div></div>

<div><span class="lbl">Battery cells</span><div class="card demo-card"><div class="card-body p-4">
<div class="dk batt">
  <div class="dk-head d-flex flex-wrap justify-content-between align-items-baseline column-gap-3 row-gap-1"><b class="fw-semibold" id="dk-batt">Charging</b><span class="fw-bold dk-val" aria-hidden="true">60%</span></div>
  <div class="dk-batt d-flex align-items-center gap-1">
    <div class="dk-cells flex-grow-1" role="progressbar" aria-labelledby="dk-batt" aria-valuenow="60" aria-valuemin="0" aria-valuemax="100" aria-valuetext="60%, 48 minutes to full">
      <i class="on"></i><i class="on"></i><i class="on"></i><i class="on"></i><i class="on"></i><i class="on"></i><i class="next"></i><i></i><i></i><i></i>
    </div>
  </div>
  <p class="dk-note mb-0">48 minutes to full · Fast charging</p>
</div></div></div></div>

<div><span class="lbl">Glow ring</span><div class="card demo-card"><div class="card-body p-4">
<div class="dk ring d-flex align-items-center gap-4">
  <div class="dk-ring position-relative flex-shrink-0 d-grid" style="--v:70;place-items:center" role="progressbar" aria-labelledby="dk-sync" aria-valuenow="70" aria-valuemin="0" aria-valuemax="100" aria-valuetext="70%, 1,204 of 1,720 photos"><span aria-hidden="true"></span><b class="position-relative" aria-hidden="true">70%</b></div>
  <div class="dk-ring-txt"><b class="d-block fw-semibold" id="dk-sync">Syncing photo library</b><p><strong>1,204</strong> of 1,720 photos</p><p>About 6 minutes left on Wi-Fi</p></div>
</div></div></div></div>

<div><span class="lbl">Level and XP</span><div class="card demo-card"><div class="card-body p-4">
<div class="dk level">
  <div class="dk-head d-flex flex-wrap justify-content-between align-items-baseline column-gap-3 row-gap-1"><b class="fw-semibold" id="dk-xp">Level progress</b><span class="fw-bold dk-val" aria-hidden="true">2,340 / 3,000 XP</span></div>
  <div class="dk-xp d-flex align-items-center gap-3">
    <span class="dk-lvl d-grid flex-shrink-0" style="place-items:center" aria-hidden="true">12</span>
    <div class="progress flex-grow-1" role="progressbar" aria-labelledby="dk-xp" aria-valuenow="2340" aria-valuemin="0" aria-valuemax="3000" aria-valuetext="Level 12, 2,340 of 3,000 XP to level 13"><div class="progress-bar" style="width:78%"></div></div>
    <span class="dk-lvl next d-grid flex-shrink-0" style="place-items:center" aria-hidden="true">13</span>
  </div>
  <p class="dk-note mb-0">660 XP to level 13 · Finish two more lessons today</p>
</div></div></div></div>
CSS
/* Dark progress bars on Bootstrap .progress (neon and level bars); the battery cells and the glow ring are a small
   stylesheet because Bootstrap has no segmented or circular progress. role="progressbar" with aria-value* on each.
   Bootstrap stops its own bar transition under prefers-reduced-motion; the rules below stop the sheen and the pulse. */
.dk{--dk-track:#26304a;--dk-ink:#e5e9f2;--dk-muted:#98a3bb;color:var(--dk-ink)}
.dk .dk-head{font-size:.92rem}
.dk>.progress,.dk .dk-batt,.dk .dk-xp{margin-top:12px}
.dk .dk-note{margin-top:10px;font-size:.82rem;color:var(--dk-muted)}
/* neon: a gradient fill with a glow and a sheen that sweeps across it */
.dk .progress{--bs-progress-height:10px;--bs-progress-bg:var(--dk-track);--bs-progress-border-radius:999px;overflow:visible}
.dk .progress-bar{position:relative;border-radius:inherit;background:linear-gradient(90deg,#22d3ee,#a78bfa);
  box-shadow:0 0 14px rgba(34,211,238,.45),0 0 4px rgba(167,139,250,.6)}
.dk .progress-bar::after{content:"";position:absolute;inset:0;transform:translateX(-100%);
  background:linear-gradient(90deg,transparent,rgba(255,255,255,.55),transparent);animation:dk-sheen 2.4s ease-in-out infinite}
@keyframes dk-sheen{60%,to{transform:translateX(100%)}}
.dk.neon .dk-val{color:#67e8f9}
/* battery: ten LED cells; the next cell pulses while charging */
.dk .dk-cells{display:grid;grid-template-columns:repeat(10,1fr);gap:4px;padding:4px;border:2px solid #4b587a;border-radius:9px}
.dk .dk-cells i{height:22px;border-radius:3px;background:var(--dk-track)}
.dk .dk-cells i.on{background:#a3e635;box-shadow:0 0 8px rgba(163,230,53,.55)}
.dk .dk-cells i.next{background:#a3e635;animation:dk-pulse 1.4s ease-in-out infinite}
@keyframes dk-pulse{0%,100%{opacity:.25}50%{opacity:1}}
.dk .dk-batt::after{content:"";width:5px;height:14px;border-radius:0 3px 3px 0;background:#4b587a}
.dk.batt .dk-val{color:#bef264}
/* glow ring: the glow is a drop-shadow on the ring's wrapper so the mask does not clip it */
.dk .dk-ring{--v:0;width:112px;height:112px}
.dk .dk-ring>span{position:absolute;inset:0;filter:drop-shadow(0 0 6px rgba(244,114,182,.55))}
.dk .dk-ring>span::before{content:"";position:absolute;inset:0;border-radius:50%;
  background:conic-gradient(#f472b6 calc(var(--v) * 1%),var(--dk-track) 0);
  -webkit-mask:radial-gradient(farthest-side,transparent calc(100% - 9px),#000 calc(100% - 8px));
  mask:radial-gradient(farthest-side,transparent calc(100% - 9px),#000 calc(100% - 8px))}
.dk .dk-ring b{font-size:1.5rem;font-variant-numeric:tabular-nums}
.dk .dk-ring-txt p{margin:4px 0 0;font-size:.84rem;color:var(--dk-muted);font-variant-numeric:tabular-nums}
.dk .dk-ring-txt strong{color:#f9a8d4}
/* level: badges at both ends of the bar */
.dk .dk-lvl{width:38px;height:38px;border-radius:11px;font-size:.9rem;font-weight:800;background:linear-gradient(135deg,#fbbf24,#f472b6);color:#1a1020}
.dk .dk-lvl.next{background:transparent;border:2px solid #4b587a;color:var(--dk-muted)}
.dk.level .progress{--bs-progress-height:12px}
.dk.level .progress-bar{background:linear-gradient(90deg,#fbbf24,#f472b6);box-shadow:0 0 12px rgba(244,114,182,.4)}
.dk.level .dk-val{color:#fcd34d}
@media (prefers-reduced-motion:reduce){
  .dk .progress-bar::after{animation:none;display:none}
  .dk .dk-cells i.next{animation:none;opacity:.45}
}

Tailwind 4 code

Requires: Tailwind CSS 4

HTML
<div><span class="mb-3 block text-[.72rem] tracking-[.12em] text-dk-muted uppercase">Neon gradient</span><div class="rounded-2xl border border-[#1f2842] bg-dk-card px-6 pt-[22px] pb-6">
<div>
  <div class="flex flex-wrap items-baseline justify-between gap-x-3 gap-y-1 text-[.92rem]"><b class="font-semibold" id="dk-deploy">Deploying api-gateway to production</b><span class="font-bold text-[#67e8f9] tabular-nums" aria-hidden="true">76%</span></div>
  <div class="mt-3 h-2.5 rounded-full bg-dk-track" role="progressbar" aria-labelledby="dk-deploy" aria-valuenow="76" aria-valuemin="0" aria-valuemax="100" aria-valuetext="76%, step 4 of 5, running health checks"><div class="relative h-full w-[76%] overflow-hidden rounded-full bg-linear-to-r from-[#22d3ee] to-[#a78bfa] shadow-[0_0_14px_rgba(34,211,238,.45),0_0_4px_rgba(167,139,250,.6)] after:absolute after:inset-0 after:animate-dk-sheen after:bg-[linear-gradient(90deg,transparent,rgba(255,255,255,.55),transparent)] after:content-[''] motion-reduce:after:hidden"></div></div>
  <p class="mt-2.5 text-[.82rem] text-dk-muted">Step 4 of 5 · Running health checks on 12 pods</p>
</div></div></div>

<div><span class="mb-3 block text-[.72rem] tracking-[.12em] text-dk-muted uppercase">Battery cells</span><div class="rounded-2xl border border-[#1f2842] bg-dk-card px-6 pt-[22px] pb-6">
<div>
  <div class="flex flex-wrap items-baseline justify-between gap-x-3 gap-y-1 text-[.92rem]"><b class="font-semibold" id="dk-batt">Charging</b><span class="font-bold text-[#bef264] tabular-nums" aria-hidden="true">60%</span></div>
  <div class="mt-3 flex items-center gap-1 after:h-3.5 after:w-[5px] after:rounded-r-[3px] after:bg-dk-edge after:content-['']">
    <div class="grid flex-1 grid-cols-10 gap-1 rounded-[9px] border-2 border-dk-edge p-1" role="progressbar" aria-labelledby="dk-batt" aria-valuenow="60" aria-valuemin="0" aria-valuemax="100" aria-valuetext="60%, 48 minutes to full">
      <i class="h-[22px] rounded-[3px] bg-dk-lime shadow-[0_0_8px_rgba(163,230,53,.55)]"></i><i class="h-[22px] rounded-[3px] bg-dk-lime shadow-[0_0_8px_rgba(163,230,53,.55)]"></i><i class="h-[22px] rounded-[3px] bg-dk-lime shadow-[0_0_8px_rgba(163,230,53,.55)]"></i><i class="h-[22px] rounded-[3px] bg-dk-lime shadow-[0_0_8px_rgba(163,230,53,.55)]"></i><i class="h-[22px] rounded-[3px] bg-dk-lime shadow-[0_0_8px_rgba(163,230,53,.55)]"></i><i class="h-[22px] rounded-[3px] bg-dk-lime shadow-[0_0_8px_rgba(163,230,53,.55)]"></i><i class="h-[22px] animate-dk-pulse rounded-[3px] bg-dk-lime motion-reduce:animate-none motion-reduce:opacity-45"></i><i class="h-[22px] rounded-[3px] bg-dk-track"></i><i class="h-[22px] rounded-[3px] bg-dk-track"></i><i class="h-[22px] rounded-[3px] bg-dk-track"></i>
    </div>
  </div>
  <p class="mt-2.5 text-[.82rem] text-dk-muted">48 minutes to full · Fast charging</p>
</div></div></div>

<div><span class="mb-3 block text-[.72rem] tracking-[.12em] text-dk-muted uppercase">Glow ring</span><div class="rounded-2xl border border-[#1f2842] bg-dk-card px-6 pt-[22px] pb-6">
<div class="flex items-center gap-[22px]">
  <div class="relative grid size-28 flex-none place-items-center" role="progressbar" aria-labelledby="dk-sync" aria-valuenow="70" aria-valuemin="0" aria-valuemax="100" aria-valuetext="70%, 1,204 of 1,720 photos"><span class="absolute inset-0 drop-shadow-[0_0_6px_rgba(244,114,182,.55)] before:absolute before:inset-0 before:rounded-full before:bg-[conic-gradient(#f472b6_70%,var(--color-dk-track)_0)] before:[mask:radial-gradient(farthest-side,transparent_calc(100%_-_9px),#000_calc(100%_-_8px))] before:content-['']" aria-hidden="true"></span><b class="relative text-2xl tabular-nums" aria-hidden="true">70%</b></div>
  <div><b class="block font-semibold" id="dk-sync">Syncing photo library</b><p class="mt-1 text-[.84rem] text-dk-muted tabular-nums"><strong class="text-[#f9a8d4]">1,204</strong> of 1,720 photos</p><p class="mt-1 text-[.84rem] text-dk-muted">About 6 minutes left on Wi-Fi</p></div>
</div></div></div>

<div><span class="mb-3 block text-[.72rem] tracking-[.12em] text-dk-muted uppercase">Level and XP</span><div class="rounded-2xl border border-[#1f2842] bg-dk-card px-6 pt-[22px] pb-6">
<div>
  <div class="flex flex-wrap items-baseline justify-between gap-x-3 gap-y-1 text-[.92rem]"><b class="font-semibold" id="dk-xp">Level progress</b><span class="font-bold text-[#fcd34d] tabular-nums" aria-hidden="true">2,340 / 3,000 XP</span></div>
  <div class="mt-3 flex items-center gap-3">
    <span class="grid size-[38px] flex-none place-items-center rounded-[11px] bg-linear-135 from-[#fbbf24] to-[#f472b6] text-[.9rem] font-extrabold text-[#1a1020]" aria-hidden="true">12</span>
    <div class="h-3 flex-1 rounded-full bg-dk-track" role="progressbar" aria-labelledby="dk-xp" aria-valuenow="2340" aria-valuemin="0" aria-valuemax="3000" aria-valuetext="Level 12, 2,340 of 3,000 XP to level 13"><div class="relative h-full w-[78%] overflow-hidden rounded-full bg-linear-to-r from-[#fbbf24] to-[#f472b6] shadow-[0_0_12px_rgba(244,114,182,.4)] after:absolute after:inset-0 after:animate-dk-sheen after:bg-[linear-gradient(90deg,transparent,rgba(255,255,255,.55),transparent)] after:content-[''] motion-reduce:after:hidden"></div></div>
    <span class="grid size-[38px] flex-none place-items-center rounded-[11px] border-2 border-dk-edge text-[.9rem] font-extrabold text-dk-muted" aria-hidden="true">13</span>
  </div>
  <p class="mt-2.5 text-[.82rem] text-dk-muted">660 XP to level 13 · Finish two more lessons today</p>
</div></div></div>
CSS
@theme {
  --color-dk-card: #121829;
  --color-dk-track: #26304a;
  --color-dk-edge: #4b587a;
  --color-dk-ink: #e5e9f2;
  --color-dk-muted: #98a3bb;
  --color-dk-lime: #a3e635;
  --animate-dk-sheen: dk-sheen 2.4s ease-in-out infinite;
  --animate-dk-pulse: dk-pulse 1.4s ease-in-out infinite;
  @keyframes dk-sheen { 0% { transform: translateX(-100%); } 60%, 100% { transform: translateX(100%); } }
  @keyframes dk-pulse { 0%, 100% { opacity: .25; } 50% { opacity: 1; } }
}

About this set

Progress bars for dark dashboards, developer tools, games and night-mode apps, where a light-theme bar looks flat. Neon gradient runs a cyan to violet fill with a soft glow and a sheen that sweeps across it, shown on a production deploy at step 4 of 5. Battery cells draws ten LED cells inside a battery outline with a terminal nub; six are lit with a green glow and the seventh pulses to show charging. Glow ring is a pink conic ring with a drop-shadow halo next to a photo library sync count; the glow sits on a wrapper around the masked ring, because a filter on the masked element itself would be clipped by the mask. Level and XP puts level badges at both ends of an amber to pink bar for 2,340 of 3,000 XP. Tracks use a mid slate that stays visible on the dark card, the values use light tints of each accent so they read at 4.5:1, and every bar is role=”progressbar” with its context in aria-valuetext. The sheen and the charging pulse are CSS keyframes that stop under prefers-reduced-motion, leaving the next battery cell dimly lit.

What’s included

  • Neon gradient bar with glow and sheen
  • Battery with LED cells and a charging pulse
  • Glow ring with a drop-shadow halo
  • Level badges around an XP bar
  • Sheen and pulse stop under prefers-reduced-motion
  • Plain CSS, Bootstrap and Tailwind versions of the same design

Accessibility

Each bar, battery and ring is role="progressbar" with aria-valuenow, aria-valuemin and aria-valuemax, named by its visible label and given context in aria-valuetext, such as 60%, 48 minutes to full. Values and notes use light tints that meet 4.5:1 on the dark card, and the level badges are aria-hidden because the bar already says which level it leads to. The sheen and the pulse stop under prefers-reduced-motion.

Customise it

Change --dk-track on .dk and the gradient stops on the fills in the plain CSS and Bootstrap versions; Bootstrap bars also take --bs-progress-height and --bs-progress-bg. In Tailwind edit the dk- theme colours and the from- and to- gradient classes.