SLA Uptime Percentage Indicator
The status-page header, rebuilt: 99.982% uptime counting up across four significant digits, a 90-day incident history strip, and an operational badge — all in pure CSS. The interesting problem is decimals, because CSS counters are integers only; the fix is two counters and a literal separator, and it is exact.
Published Updated
The code
<section class="cnc-16" aria-label="SLA uptime percentage indicator demo">
<div class="cnc-16__stage">
<article class="cnc-16__panel">
<header class="cnc-16__top">
<span class="cnc-16__badge"><span class="cnc-16__dot" aria-hidden="true"></span>All systems operational</span>
<span class="cnc-16__region">us-east · eu-west · ap-south</span>
</header>
<p class="cnc-16__pct" aria-hidden="true"></p>
<p class="cnc-16__sr">99.982 percent uptime over the last 90 days</p>
<p class="cnc-16__sub">90-day uptime · SLA commitment 99.95%</p>
<div class="cnc-16__strip" aria-hidden="true">
<span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span>
<span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span>
<span></span><span></span><span></span><span data-s="warn" title="14 Jun — 12 min elevated latency"></span><span></span><span></span><span></span><span></span><span></span><span></span>
<span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span>
<span></span><span></span><span></span><span></span><span></span><span></span><span data-s="down" title="6 Jul — 4 min partial outage"></span><span></span><span></span><span></span>
<span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span>
<span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span>
<span></span><span data-s="warn" title="2 Aug — 6 min degraded search"></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span>
<span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span>
</div>
<footer class="cnc-16__foot"><span>90 days ago</span><span>3 incidents · 22 min total</span><span>Today</span></footer>
</article>
<p class="cnc-16__chip" aria-hidden="true">two counters + literal separator · @counter-style pad · 90 CSS bars</p>
</div>
</section><section class="cnc-16" aria-label="SLA uptime percentage indicator demo">
<div class="cnc-16__stage">
<article class="cnc-16__panel">
<header class="cnc-16__top">
<span class="cnc-16__badge"><span class="cnc-16__dot" aria-hidden="true"></span>All systems operational</span>
<span class="cnc-16__region">us-east · eu-west · ap-south</span>
</header>
<p class="cnc-16__pct" aria-hidden="true"></p>
<p class="cnc-16__sr">99.982 percent uptime over the last 90 days</p>
<p class="cnc-16__sub">90-day uptime · SLA commitment 99.95%</p>
<div class="cnc-16__strip" aria-hidden="true">
<span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span>
<span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span>
<span></span><span></span><span></span><span data-s="warn" title="14 Jun — 12 min elevated latency"></span><span></span><span></span><span></span><span></span><span></span><span></span>
<span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span>
<span></span><span></span><span></span><span></span><span></span><span></span><span data-s="down" title="6 Jul — 4 min partial outage"></span><span></span><span></span><span></span>
<span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span>
<span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span>
<span></span><span data-s="warn" title="2 Aug — 6 min degraded search"></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span>
<span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span>
</div>
<footer class="cnc-16__foot"><span>90 days ago</span><span>3 incidents · 22 min total</span><span>Today</span></footer>
</article>
<p class="cnc-16__chip" aria-hidden="true">two counters + literal separator · @counter-style pad · 90 CSS bars</p>
</div>
</section>@property --cnc-16-i {
syntax: '<integer>';
inherits: false;
initial-value: 0;
}
@property --cnc-16-f {
syntax: '<integer>';
inherits: false;
initial-value: 0;
}
@counter-style cnc-16-pad3 {
system: numeric;
symbols: '0' '1' '2' '3' '4' '5' '6' '7' '8' '9';
pad: 3 '0';
}
.cnc-16,
.cnc-16 *,
.cnc-16 *::before,
.cnc-16 *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.cnc-16 {
width: 100%;
min-height: 100vh;
min-height: 100svh;
display: block;
--cnc-16-bg: oklch(0.16 0.015 240);
--cnc-16-card: oklch(0.21 0.018 240);
--cnc-16-ink: oklch(0.98 0.004 240);
--cnc-16-mut: oklch(0.66 0.02 240);
--cnc-16-ok: oklch(0.78 0.16 152);
--cnc-16-warn: oklch(0.8 0.15 80);
--cnc-16-bad: oklch(0.68 0.2 25);
background: var(--cnc-16-bg);
color: var(--cnc-16-ink);
font-family: 'Segoe UI',system-ui,-apple-system,sans-serif;
}
.cnc-16__stage {
min-height: 100vh;
min-height: 100svh;
display: grid;
place-items: center;
align-content: center;
gap: 18px;
padding: clamp(18px,4vw,48px);
}
.cnc-16__panel {
width: min(100%,640px);
padding: clamp(22px,4vw,32px);
border-radius: 22px;
background: var(--cnc-16-card);
box-shadow: inset 0 0 0 1px oklch(1 0 0/.07),0 24px 56px oklch(0 0 0/.42);
}
.cnc-16__top {
display: flex;
flex-wrap: wrap;
align-items: center;
justify-content: space-between;
gap: 10px;
}
.cnc-16__badge {
display: inline-flex;
align-items: center;
gap: 8px;
padding: 6px 12px;
border-radius: 99px;
background: color-mix(in oklch,var(--cnc-16-ok) 15%,transparent);
color: var(--cnc-16-ok);
font-size: 12.5px;
font-weight: 680;
}
.cnc-16__dot {
position: relative;
width: 8px;
height: 8px;
border-radius: 50%;
background: currentColor;
}
.cnc-16__dot::after {
content: "";
position: absolute;
inset: 0;
border-radius: 50%;
background: currentColor;
animation: cnc-16-ping 2.4s cubic-bezier(0,0,.2,1) infinite;
}
@keyframes cnc-16-ping {
0% {
opacity: .6;
scale: 1;
}
75%,
100% {
opacity: 0;
scale: 3;
}
}
.cnc-16__region {
font-family: ui-monospace,Menlo,Consolas,monospace;
font-size: 11.5px;
color: var(--cnc-16-mut);
}
.cnc-16__pct {
margin-top: 22px;
font-size: clamp(44px,9vw,72px);
font-weight: 750;
letter-spacing: -.055em;
line-height: 1;
color: var(--cnc-16-ok);
font-variant-numeric: tabular-nums;
font-feature-settings: 'tnum' 1;
counter-reset: cnc-16-i var(--cnc-16-i) cnc-16-f var(--cnc-16-f);
animation: cnc-16-count 2.6s cubic-bezier(.16,1,.3,1) both;
}
.cnc-16__pct::after {
content: counter(cnc-16-i) "." counter(cnc-16-f,cnc-16-pad3) "%";
}
@keyframes cnc-16-count {
from {
--cnc-16-i: 0;
--cnc-16-f: 0;
}
to {
--cnc-16-i: 99;
--cnc-16-f: 982;
}
}
.cnc-16__sub {
margin-top: 10px;
font-size: 13px;
color: var(--cnc-16-mut);
}
.cnc-16__strip {
display: flex;
gap: 2px;
height: 44px;
margin-top: 26px;
}
.cnc-16__strip span {
flex: 1;
border-radius: 3px;
background: color-mix(in oklch,var(--cnc-16-ok) 55%,transparent);
transform-origin: bottom;
animation: cnc-16-rise .5s cubic-bezier(.16,1,.3,1) both;
transition: background .2s,transform .2s;
}
.cnc-16__strip span:hover {
background: var(--cnc-16-ok);
transform: scaleY(1.08);
}
.cnc-16__strip span[data-s="warn"] {
background: var(--cnc-16-warn);
}
.cnc-16__strip span[data-s="down"] {
background: var(--cnc-16-bad);
}
@keyframes cnc-16-rise {
from {
transform: scaleY(.15);
opacity: .2;
}
to {
transform: scaleY(1);
opacity: 1;
}
}
.cnc-16__strip span:nth-child(3n) {
animation-delay: .05s;
}
.cnc-16__strip span:nth-child(3n+1) {
animation-delay: .12s;
}
.cnc-16__strip span:nth-child(5n) {
animation-delay: .2s;
}
.cnc-16__foot {
display: flex;
justify-content: space-between;
gap: 10px;
margin-top: 12px;
font-size: 11.5px;
color: var(--cnc-16-mut);
}
.cnc-16__sr {
position: absolute;
width: 1px;
height: 1px;
overflow: hidden;
clip-path: inset(50%);
white-space: nowrap;
}
.cnc-16__chip {
font-family: ui-monospace,Menlo,Consolas,monospace;
font-size: 11.5px;
color: var(--cnc-16-mut);
padding: 7px 14px;
border: 1px solid oklch(1 0 0/.13);
border-radius: 99px;
text-align: center;
max-width: min(100%,560px);
}
@media (prefers-reduced-motion: reduce) {
.cnc-16__pct {
animation-duration: 1ms;
}
.cnc-16__strip span {
animation: none;
}
.cnc-16__dot::after {
animation: none;
opacity: 0;
}
}@property --cnc-16-i {
syntax: '<integer>';
inherits: false;
initial-value: 0;
}
@property --cnc-16-f {
syntax: '<integer>';
inherits: false;
initial-value: 0;
}
@counter-style cnc-16-pad3 {
system: numeric;
symbols: '0' '1' '2' '3' '4' '5' '6' '7' '8' '9';
pad: 3 '0';
}
.cnc-16,
.cnc-16 *,
.cnc-16 *::before,
.cnc-16 *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.cnc-16 {
width: 100%;
min-height: 100vh;
min-height: 100svh;
display: block;
--cnc-16-bg: oklch(0.16 0.015 240);
--cnc-16-card: oklch(0.21 0.018 240);
--cnc-16-ink: oklch(0.98 0.004 240);
--cnc-16-mut: oklch(0.66 0.02 240);
--cnc-16-ok: oklch(0.78 0.16 152);
--cnc-16-warn: oklch(0.8 0.15 80);
--cnc-16-bad: oklch(0.68 0.2 25);
background: var(--cnc-16-bg);
color: var(--cnc-16-ink);
font-family: 'Segoe UI',system-ui,-apple-system,sans-serif;
}
.cnc-16__stage {
min-height: 100vh;
min-height: 100svh;
display: grid;
place-items: center;
align-content: center;
gap: 18px;
padding: clamp(18px,4vw,48px);
}
.cnc-16__panel {
width: min(100%,640px);
padding: clamp(22px,4vw,32px);
border-radius: 22px;
background: var(--cnc-16-card);
box-shadow: inset 0 0 0 1px oklch(1 0 0/.07),0 24px 56px oklch(0 0 0/.42);
}
.cnc-16__top {
display: flex;
flex-wrap: wrap;
align-items: center;
justify-content: space-between;
gap: 10px;
}
.cnc-16__badge {
display: inline-flex;
align-items: center;
gap: 8px;
padding: 6px 12px;
border-radius: 99px;
background: color-mix(in oklch,var(--cnc-16-ok) 15%,transparent);
color: var(--cnc-16-ok);
font-size: 12.5px;
font-weight: 680;
}
.cnc-16__dot {
position: relative;
width: 8px;
height: 8px;
border-radius: 50%;
background: currentColor;
}
.cnc-16__dot::after {
content: "";
position: absolute;
inset: 0;
border-radius: 50%;
background: currentColor;
animation: cnc-16-ping 2.4s cubic-bezier(0,0,.2,1) infinite;
}
@keyframes cnc-16-ping {
0% {
opacity: .6;
scale: 1;
}
75%,
100% {
opacity: 0;
scale: 3;
}
}
.cnc-16__region {
font-family: ui-monospace,Menlo,Consolas,monospace;
font-size: 11.5px;
color: var(--cnc-16-mut);
}
.cnc-16__pct {
margin-top: 22px;
font-size: clamp(44px,9vw,72px);
font-weight: 750;
letter-spacing: -.055em;
line-height: 1;
color: var(--cnc-16-ok);
font-variant-numeric: tabular-nums;
font-feature-settings: 'tnum' 1;
counter-reset: cnc-16-i var(--cnc-16-i) cnc-16-f var(--cnc-16-f);
animation: cnc-16-count 2.6s cubic-bezier(.16,1,.3,1) both;
}
.cnc-16__pct::after {
content: counter(cnc-16-i) "." counter(cnc-16-f,cnc-16-pad3) "%";
}
@keyframes cnc-16-count {
from {
--cnc-16-i: 0;
--cnc-16-f: 0;
}
to {
--cnc-16-i: 99;
--cnc-16-f: 982;
}
}
.cnc-16__sub {
margin-top: 10px;
font-size: 13px;
color: var(--cnc-16-mut);
}
.cnc-16__strip {
display: flex;
gap: 2px;
height: 44px;
margin-top: 26px;
}
.cnc-16__strip span {
flex: 1;
border-radius: 3px;
background: color-mix(in oklch,var(--cnc-16-ok) 55%,transparent);
transform-origin: bottom;
animation: cnc-16-rise .5s cubic-bezier(.16,1,.3,1) both;
transition: background .2s,transform .2s;
}
.cnc-16__strip span:hover {
background: var(--cnc-16-ok);
transform: scaleY(1.08);
}
.cnc-16__strip span[data-s="warn"] {
background: var(--cnc-16-warn);
}
.cnc-16__strip span[data-s="down"] {
background: var(--cnc-16-bad);
}
@keyframes cnc-16-rise {
from {
transform: scaleY(.15);
opacity: .2;
}
to {
transform: scaleY(1);
opacity: 1;
}
}
.cnc-16__strip span:nth-child(3n) {
animation-delay: .05s;
}
.cnc-16__strip span:nth-child(3n+1) {
animation-delay: .12s;
}
.cnc-16__strip span:nth-child(5n) {
animation-delay: .2s;
}
.cnc-16__foot {
display: flex;
justify-content: space-between;
gap: 10px;
margin-top: 12px;
font-size: 11.5px;
color: var(--cnc-16-mut);
}
.cnc-16__sr {
position: absolute;
width: 1px;
height: 1px;
overflow: hidden;
clip-path: inset(50%);
white-space: nowrap;
}
.cnc-16__chip {
font-family: ui-monospace,Menlo,Consolas,monospace;
font-size: 11.5px;
color: var(--cnc-16-mut);
padding: 7px 14px;
border: 1px solid oklch(1 0 0/.13);
border-radius: 99px;
text-align: center;
max-width: min(100%,560px);
}
@media (prefers-reduced-motion: reduce) {
.cnc-16__pct {
animation-duration: 1ms;
}
.cnc-16__strip span {
animation: none;
}
.cnc-16__dot::after {
animation: none;
opacity: 0;
}
}Here's a working CSS Number Counter Animation from CodeFronts. Use it as-is or adapt to your framework. All classes are scoped under a unique prefix so the code won't collide with your existing styles. MIT licensed.
Demo: SLA Uptime Percentage Indicator
Source: https://codefronts.com/motion/css-number-counter-animations/uptime-sla-monitor/
The status-page header, rebuilt: 99.982% uptime counting up across four significant digits, a 90-day incident history strip, and an operational badge — all in pure CSS. The interesting problem is decimals, because CSS counters are integers only; the fix is two counters and a literal separator, and it is exact.
## HTML
```html
<section class="cnc-16" aria-label="SLA uptime percentage indicator demo">
<div class="cnc-16__stage">
<article class="cnc-16__panel">
<header class="cnc-16__top">
<span class="cnc-16__badge"><span class="cnc-16__dot" aria-hidden="true"></span>All systems operational</span>
<span class="cnc-16__region">us-east · eu-west · ap-south</span>
</header>
<p class="cnc-16__pct" aria-hidden="true"></p>
<p class="cnc-16__sr">99.982 percent uptime over the last 90 days</p>
<p class="cnc-16__sub">90-day uptime · SLA commitment 99.95%</p>
<div class="cnc-16__strip" aria-hidden="true">
<span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span>
<span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span>
<span></span><span></span><span></span><span data-s="warn" title="14 Jun — 12 min elevated latency"></span><span></span><span></span><span></span><span></span><span></span><span></span>
<span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span>
<span></span><span></span><span></span><span></span><span></span><span></span><span data-s="down" title="6 Jul — 4 min partial outage"></span><span></span><span></span><span></span>
<span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span>
<span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span>
<span></span><span data-s="warn" title="2 Aug — 6 min degraded search"></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span>
<span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span>
</div>
<footer class="cnc-16__foot"><span>90 days ago</span><span>3 incidents · 22 min total</span><span>Today</span></footer>
</article>
<p class="cnc-16__chip" aria-hidden="true">two counters + literal separator · @counter-style pad · 90 CSS bars</p>
</div>
</section>
```
## CSS
```css
@property --cnc-16-i {
syntax: '<integer>';
inherits: false;
initial-value: 0;
}
@property --cnc-16-f {
syntax: '<integer>';
inherits: false;
initial-value: 0;
}
@counter-style cnc-16-pad3 {
system: numeric;
symbols: '0' '1' '2' '3' '4' '5' '6' '7' '8' '9';
pad: 3 '0';
}
.cnc-16,
.cnc-16 *,
.cnc-16 *::before,
.cnc-16 *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.cnc-16 {
width: 100%;
min-height: 100vh;
min-height: 100svh;
display: block;
--cnc-16-bg: oklch(0.16 0.015 240);
--cnc-16-card: oklch(0.21 0.018 240);
--cnc-16-ink: oklch(0.98 0.004 240);
--cnc-16-mut: oklch(0.66 0.02 240);
--cnc-16-ok: oklch(0.78 0.16 152);
--cnc-16-warn: oklch(0.8 0.15 80);
--cnc-16-bad: oklch(0.68 0.2 25);
background: var(--cnc-16-bg);
color: var(--cnc-16-ink);
font-family: 'Segoe UI',system-ui,-apple-system,sans-serif;
}
.cnc-16__stage {
min-height: 100vh;
min-height: 100svh;
display: grid;
place-items: center;
align-content: center;
gap: 18px;
padding: clamp(18px,4vw,48px);
}
.cnc-16__panel {
width: min(100%,640px);
padding: clamp(22px,4vw,32px);
border-radius: 22px;
background: var(--cnc-16-card);
box-shadow: inset 0 0 0 1px oklch(1 0 0/.07),0 24px 56px oklch(0 0 0/.42);
}
.cnc-16__top {
display: flex;
flex-wrap: wrap;
align-items: center;
justify-content: space-between;
gap: 10px;
}
.cnc-16__badge {
display: inline-flex;
align-items: center;
gap: 8px;
padding: 6px 12px;
border-radius: 99px;
background: color-mix(in oklch,var(--cnc-16-ok) 15%,transparent);
color: var(--cnc-16-ok);
font-size: 12.5px;
font-weight: 680;
}
.cnc-16__dot {
position: relative;
width: 8px;
height: 8px;
border-radius: 50%;
background: currentColor;
}
.cnc-16__dot::after {
content: "";
position: absolute;
inset: 0;
border-radius: 50%;
background: currentColor;
animation: cnc-16-ping 2.4s cubic-bezier(0,0,.2,1) infinite;
}
@keyframes cnc-16-ping {
0% {
opacity: .6;
scale: 1;
}
75%,
100% {
opacity: 0;
scale: 3;
}
}
.cnc-16__region {
font-family: ui-monospace,Menlo,Consolas,monospace;
font-size: 11.5px;
color: var(--cnc-16-mut);
}
.cnc-16__pct {
margin-top: 22px;
font-size: clamp(44px,9vw,72px);
font-weight: 750;
letter-spacing: -.055em;
line-height: 1;
color: var(--cnc-16-ok);
font-variant-numeric: tabular-nums;
font-feature-settings: 'tnum' 1;
counter-reset: cnc-16-i var(--cnc-16-i) cnc-16-f var(--cnc-16-f);
animation: cnc-16-count 2.6s cubic-bezier(.16,1,.3,1) both;
}
.cnc-16__pct::after {
content: counter(cnc-16-i) "." counter(cnc-16-f,cnc-16-pad3) "%";
}
@keyframes cnc-16-count {
from {
--cnc-16-i: 0;
--cnc-16-f: 0;
}
to {
--cnc-16-i: 99;
--cnc-16-f: 982;
}
}
.cnc-16__sub {
margin-top: 10px;
font-size: 13px;
color: var(--cnc-16-mut);
}
.cnc-16__strip {
display: flex;
gap: 2px;
height: 44px;
margin-top: 26px;
}
.cnc-16__strip span {
flex: 1;
border-radius: 3px;
background: color-mix(in oklch,var(--cnc-16-ok) 55%,transparent);
transform-origin: bottom;
animation: cnc-16-rise .5s cubic-bezier(.16,1,.3,1) both;
transition: background .2s,transform .2s;
}
.cnc-16__strip span:hover {
background: var(--cnc-16-ok);
transform: scaleY(1.08);
}
.cnc-16__strip span[data-s="warn"] {
background: var(--cnc-16-warn);
}
.cnc-16__strip span[data-s="down"] {
background: var(--cnc-16-bad);
}
@keyframes cnc-16-rise {
from {
transform: scaleY(.15);
opacity: .2;
}
to {
transform: scaleY(1);
opacity: 1;
}
}
.cnc-16__strip span:nth-child(3n) {
animation-delay: .05s;
}
.cnc-16__strip span:nth-child(3n+1) {
animation-delay: .12s;
}
.cnc-16__strip span:nth-child(5n) {
animation-delay: .2s;
}
.cnc-16__foot {
display: flex;
justify-content: space-between;
gap: 10px;
margin-top: 12px;
font-size: 11.5px;
color: var(--cnc-16-mut);
}
.cnc-16__sr {
position: absolute;
width: 1px;
height: 1px;
overflow: hidden;
clip-path: inset(50%);
white-space: nowrap;
}
.cnc-16__chip {
font-family: ui-monospace,Menlo,Consolas,monospace;
font-size: 11.5px;
color: var(--cnc-16-mut);
padding: 7px 14px;
border: 1px solid oklch(1 0 0/.13);
border-radius: 99px;
text-align: center;
max-width: min(100%,560px);
}
@media (prefers-reduced-motion: reduce) {
.cnc-16__pct {
animation-duration: 1ms;
}
.cnc-16__strip span {
animation: none;
}
.cnc-16__dot::after {
animation: none;
opacity: 0;
}
}
```Here's a working CSS Number Counter Animation from CodeFronts. Use it as-is or adapt to your framework. All classes are scoped under a unique prefix so the code won't collide with your existing styles. MIT licensed.
Demo: SLA Uptime Percentage Indicator
Source: https://codefronts.com/motion/css-number-counter-animations/uptime-sla-monitor/
The status-page header, rebuilt: 99.982% uptime counting up across four significant digits, a 90-day incident history strip, and an operational badge — all in pure CSS. The interesting problem is decimals, because CSS counters are integers only; the fix is two counters and a literal separator, and it is exact.
## HTML
```html
<section class="cnc-16" aria-label="SLA uptime percentage indicator demo">
<div class="cnc-16__stage">
<article class="cnc-16__panel">
<header class="cnc-16__top">
<span class="cnc-16__badge"><span class="cnc-16__dot" aria-hidden="true"></span>All systems operational</span>
<span class="cnc-16__region">us-east · eu-west · ap-south</span>
</header>
<p class="cnc-16__pct" aria-hidden="true"></p>
<p class="cnc-16__sr">99.982 percent uptime over the last 90 days</p>
<p class="cnc-16__sub">90-day uptime · SLA commitment 99.95%</p>
<div class="cnc-16__strip" aria-hidden="true">
<span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span>
<span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span>
<span></span><span></span><span></span><span data-s="warn" title="14 Jun — 12 min elevated latency"></span><span></span><span></span><span></span><span></span><span></span><span></span>
<span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span>
<span></span><span></span><span></span><span></span><span></span><span></span><span data-s="down" title="6 Jul — 4 min partial outage"></span><span></span><span></span><span></span>
<span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span>
<span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span>
<span></span><span data-s="warn" title="2 Aug — 6 min degraded search"></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span>
<span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span>
</div>
<footer class="cnc-16__foot"><span>90 days ago</span><span>3 incidents · 22 min total</span><span>Today</span></footer>
</article>
<p class="cnc-16__chip" aria-hidden="true">two counters + literal separator · @counter-style pad · 90 CSS bars</p>
</div>
</section>
```
## CSS
```css
@property --cnc-16-i {
syntax: '<integer>';
inherits: false;
initial-value: 0;
}
@property --cnc-16-f {
syntax: '<integer>';
inherits: false;
initial-value: 0;
}
@counter-style cnc-16-pad3 {
system: numeric;
symbols: '0' '1' '2' '3' '4' '5' '6' '7' '8' '9';
pad: 3 '0';
}
.cnc-16,
.cnc-16 *,
.cnc-16 *::before,
.cnc-16 *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.cnc-16 {
width: 100%;
min-height: 100vh;
min-height: 100svh;
display: block;
--cnc-16-bg: oklch(0.16 0.015 240);
--cnc-16-card: oklch(0.21 0.018 240);
--cnc-16-ink: oklch(0.98 0.004 240);
--cnc-16-mut: oklch(0.66 0.02 240);
--cnc-16-ok: oklch(0.78 0.16 152);
--cnc-16-warn: oklch(0.8 0.15 80);
--cnc-16-bad: oklch(0.68 0.2 25);
background: var(--cnc-16-bg);
color: var(--cnc-16-ink);
font-family: 'Segoe UI',system-ui,-apple-system,sans-serif;
}
.cnc-16__stage {
min-height: 100vh;
min-height: 100svh;
display: grid;
place-items: center;
align-content: center;
gap: 18px;
padding: clamp(18px,4vw,48px);
}
.cnc-16__panel {
width: min(100%,640px);
padding: clamp(22px,4vw,32px);
border-radius: 22px;
background: var(--cnc-16-card);
box-shadow: inset 0 0 0 1px oklch(1 0 0/.07),0 24px 56px oklch(0 0 0/.42);
}
.cnc-16__top {
display: flex;
flex-wrap: wrap;
align-items: center;
justify-content: space-between;
gap: 10px;
}
.cnc-16__badge {
display: inline-flex;
align-items: center;
gap: 8px;
padding: 6px 12px;
border-radius: 99px;
background: color-mix(in oklch,var(--cnc-16-ok) 15%,transparent);
color: var(--cnc-16-ok);
font-size: 12.5px;
font-weight: 680;
}
.cnc-16__dot {
position: relative;
width: 8px;
height: 8px;
border-radius: 50%;
background: currentColor;
}
.cnc-16__dot::after {
content: "";
position: absolute;
inset: 0;
border-radius: 50%;
background: currentColor;
animation: cnc-16-ping 2.4s cubic-bezier(0,0,.2,1) infinite;
}
@keyframes cnc-16-ping {
0% {
opacity: .6;
scale: 1;
}
75%,
100% {
opacity: 0;
scale: 3;
}
}
.cnc-16__region {
font-family: ui-monospace,Menlo,Consolas,monospace;
font-size: 11.5px;
color: var(--cnc-16-mut);
}
.cnc-16__pct {
margin-top: 22px;
font-size: clamp(44px,9vw,72px);
font-weight: 750;
letter-spacing: -.055em;
line-height: 1;
color: var(--cnc-16-ok);
font-variant-numeric: tabular-nums;
font-feature-settings: 'tnum' 1;
counter-reset: cnc-16-i var(--cnc-16-i) cnc-16-f var(--cnc-16-f);
animation: cnc-16-count 2.6s cubic-bezier(.16,1,.3,1) both;
}
.cnc-16__pct::after {
content: counter(cnc-16-i) "." counter(cnc-16-f,cnc-16-pad3) "%";
}
@keyframes cnc-16-count {
from {
--cnc-16-i: 0;
--cnc-16-f: 0;
}
to {
--cnc-16-i: 99;
--cnc-16-f: 982;
}
}
.cnc-16__sub {
margin-top: 10px;
font-size: 13px;
color: var(--cnc-16-mut);
}
.cnc-16__strip {
display: flex;
gap: 2px;
height: 44px;
margin-top: 26px;
}
.cnc-16__strip span {
flex: 1;
border-radius: 3px;
background: color-mix(in oklch,var(--cnc-16-ok) 55%,transparent);
transform-origin: bottom;
animation: cnc-16-rise .5s cubic-bezier(.16,1,.3,1) both;
transition: background .2s,transform .2s;
}
.cnc-16__strip span:hover {
background: var(--cnc-16-ok);
transform: scaleY(1.08);
}
.cnc-16__strip span[data-s="warn"] {
background: var(--cnc-16-warn);
}
.cnc-16__strip span[data-s="down"] {
background: var(--cnc-16-bad);
}
@keyframes cnc-16-rise {
from {
transform: scaleY(.15);
opacity: .2;
}
to {
transform: scaleY(1);
opacity: 1;
}
}
.cnc-16__strip span:nth-child(3n) {
animation-delay: .05s;
}
.cnc-16__strip span:nth-child(3n+1) {
animation-delay: .12s;
}
.cnc-16__strip span:nth-child(5n) {
animation-delay: .2s;
}
.cnc-16__foot {
display: flex;
justify-content: space-between;
gap: 10px;
margin-top: 12px;
font-size: 11.5px;
color: var(--cnc-16-mut);
}
.cnc-16__sr {
position: absolute;
width: 1px;
height: 1px;
overflow: hidden;
clip-path: inset(50%);
white-space: nowrap;
}
.cnc-16__chip {
font-family: ui-monospace,Menlo,Consolas,monospace;
font-size: 11.5px;
color: var(--cnc-16-mut);
padding: 7px 14px;
border: 1px solid oklch(1 0 0/.13);
border-radius: 99px;
text-align: center;
max-width: min(100%,560px);
}
@media (prefers-reduced-motion: reduce) {
.cnc-16__pct {
animation-duration: 1ms;
}
.cnc-16__strip span {
animation: none;
}
.cnc-16__dot::after {
animation: none;
opacity: 0;
}
}
```How this works
CSS counters cannot represent 99.982. So don't ask them to — animate the whole part and the fractional part as two independent integers:
@property --cnc-16-i { syntax: '<integer>'; initial-value: 0 } /* 99 */
@property --cnc-16-f { syntax: '<integer>'; initial-value: 0 } /* 982 */
.pct { counter-reset: i var(--cnc-16-i) f var(--cnc-16-f) }
.pct::after { content: counter(i) "." counter(f) "%" }Two counters in one counter-reset, one content string with a literal dot between them. Run both keyframes with the same duration and easing and they land together.
The catch is leading zeros: 99.05 would render as "99.5". Pad by animating the fraction with an offset — start the fractional counter at 1000 and subtract, or (as here) choose a target whose digit count is fixed and document it. For arbitrary values, @counter-style with a fixed pad, or splitting each decimal place into its own counter, gives you full control.
@counter-style cnc-pad3 { system: numeric; symbols: '0' '1' … '9'; pad: 3 '0' }
.pct::after { content: counter(i) "." counter(f, cnc-pad3) "%" }The 90-day strip is 90 flex children with --cnc-16-s set inline; incident days get a warmer hue through color-mix(), and each bar carries a title for hover detail. No JS, no chart, ~90 spans.
Make it yours
- True zero-padding: use the @counter-style pad rule shown above — it is the only robust way to render .05 rather than .5.
- SLA thresholds: colour the figure by comparing against your commitment with a
:has()or attribute selector — green above 99.9%, amber below. - Longer history: 90 bars is the industry norm, but the flex strip scales to 365 with
gap:1pxand no other changes. - Live data: the bars accept a data-status attribute per day — write it server-side and the CSS colours it, keeping the component static.
Gotchas — read before shipping
- counter() renders integers only. Any decimal display needs multiple counters or a padded @counter-style — this is the single most common blocker people hit with CSS counters.
- Fractional counters lose leading zeros silently: 0.05 becomes .5. Always pad deliberately.
- Rounding an SLA figure up (99.94 → 99.9%) can misstate a contractual commitment. Truncate, don't round, for uptime.
- Colour-only incident bars fail WCAG 1.4.1. Include a title/tooltip and a text summary of incident days.
- 90 animated bars with staggered delays is 90 composited layers — animate opacity only, or stagger with a shared keyframe and delay calc, as here.
Browser support
| Chrome | Safari | Firefox | Edge |
|---|---|---|---|
| 111+ | 16.4+ | 128+ | 111+ |
@property is the floor (Firefox 128+). @counter-style with pad is Chrome 91 / Safari 17 / Firefox 33. Without @property the panel renders the static, correct number from the visually-hidden text.