index.html
The finished result as one file. Save it as index.html and open it.
<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>Chart update transition</title><style>*{box-sizing:border-box;margin:0;padding:0}
html,body{width:1280px;height:720px;overflow:hidden}
body{font-family:ui-sans-serif,system-ui,-apple-system,"Segoe UI",Roboto,sans-serif;-webkit-font-smoothing:antialiased}
@property --n{syntax:'<integer>';inherits:false;initial-value:0}
.stage{position:absolute;inset:0;animation:cyc 8s linear infinite both}
@keyframes cyc{0%{opacity:0}4%{opacity:1}94%{opacity:1}100%{opacity:0}}
body:not(.go) *,body:not(.go) *::before,body:not(.go) *::after{animation-play-state:paused!important}
.cnt::after{content:counter(n)}.cnt{counter-reset:n var(--n)}
@media (prefers-reduced-motion:reduce){*{animation:none!important}}
body{background:#0b1a1a;color:#dffaf2}
.hd{position:absolute;left:56px;right:56px;top:34px;display:flex;align-items:center}
.hd h1{font-size:28px;letter-spacing:-.03em}.hd small{display:block;color:#7fb3a8;font-size:14px;margin-top:4px}
.seg{margin-left:auto;display:flex;background:#12302d;border-radius:14px;padding:5px;position:relative}
.seg b{font-size:14px;padding:10px 20px;border-radius:10px;position:relative;z-index:2;color:#7fb3a8}
.seg i{position:absolute;top:5px;left:5px;width:calc(50% - 5px);height:calc(100% - 10px);border-radius:10px;background:#14b8a6;animation:sl 8s infinite both}
@keyframes sl{0%,38%{transform:none}46%,86%{transform:translateX(100%)}94%,100%{transform:none}}
.s1{animation:c1 8s infinite both}.s2{animation:c2 8s infinite both}
@keyframes c1{0%,38%{color:#04201c}46%,86%{color:#7fb3a8}94%,100%{color:#04201c}}@keyframes c2{0%,38%{color:#7fb3a8}46%,86%{color:#04201c}94%,100%{color:#7fb3a8}}
.ch{position:absolute;left:56px;right:56px;top:140px;height:480px;background:#10282a;border-radius:24px}
.gl{position:absolute;left:70px;right:40px;height:1px;background:#1c403f}
.bars{position:absolute;left:90px;right:60px;bottom:60px;height:340px;display:flex;gap:22px;align-items:flex-end}
.bars i{flex:1;border-radius:10px 10px 4px 4px;background:linear-gradient(#2dd4bf,#0f766e);height:var(--a);animation:bar 8s infinite both;transform-origin:bottom}
@keyframes bar{0%,6%{height:0}22%,38%{height:var(--a)}50%,86%{height:var(--b)}96%,100%{height:var(--a)}}
.lb{position:absolute;left:90px;right:60px;bottom:26px;display:flex;gap:22px;font-size:13px;color:#7fb3a8}.lb span{flex:1;text-align:center}
.tp{position:absolute;left:44px;top:20px;font-size:40px;font-weight:800;letter-spacing:-.04em}.tp small{display:block;font-size:13px;color:#7fb3a8;font-weight:500;letter-spacing:0}
.n1{animation:n1 8s infinite both}@keyframes n1{0%,10%{--n:0}34%,38%{--n:284}52%,86%{--n:421}96%,100%{--n:284}}
</style></head><body><div class="stage"><div class="hd"><div><h1>Revenue by month</h1><small>Bars morph when you switch the range</small></div><div class="seg"><i></i><b class="s1">2025</b><b class="s2">2026</b></div></div>
<div class="ch"><div class="gl" style="top:90px"></div><div class="gl" style="top:170px"></div><div class="gl" style="top:250px"></div><div class="gl" style="top:330px"></div><div class="tp">$<span class="cnt n1"></span>k<small>Total</small></div><div class="bars"><i style="--a:40%;--b:62%;animation-delay:0.0s"></i><i style="--a:58%;--b:44%;animation-delay:0.04s"></i><i style="--a:46%;--b:70%;animation-delay:0.08s"></i><i style="--a:72%;--b:58%;animation-delay:0.12s"></i><i style="--a:64%;--b:86%;animation-delay:0.16s"></i><i style="--a:88%;--b:74%;animation-delay:0.2s"></i><i style="--a:70%;--b:92%;animation-delay:0.24s"></i><i style="--a:52%;--b:64%;animation-delay:0.28s"></i></div><div class="lb"><span>Jan</span><span>Feb</span><span>Mar</span><span>Apr</span><span>May</span><span>Jun</span><span>Jul</span><span>Aug</span></div></div></div><script>window.start=function(){document.body.classList.add("go")};if(!/[?&]rec/.test(location.search))start();</script></body></html>Source, 36 lines
# index.html
The finished result as one file. Save it as index.html and open it.
```html
<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>Chart update transition</title><style>*{box-sizing:border-box;margin:0;padding:0}
html,body{width:1280px;height:720px;overflow:hidden}
body{font-family:ui-sans-serif,system-ui,-apple-system,"Segoe UI",Roboto,sans-serif;-webkit-font-smoothing:antialiased}
@property --n{syntax:'<integer>';inherits:false;initial-value:0}
.stage{position:absolute;inset:0;animation:cyc 8s linear infinite both}
@keyframes cyc{0%{opacity:0}4%{opacity:1}94%{opacity:1}100%{opacity:0}}
body:not(.go) *,body:not(.go) *::before,body:not(.go) *::after{animation-play-state:paused!important}
.cnt::after{content:counter(n)}.cnt{counter-reset:n var(--n)}
@media (prefers-reduced-motion:reduce){*{animation:none!important}}
body{background:#0b1a1a;color:#dffaf2}
.hd{position:absolute;left:56px;right:56px;top:34px;display:flex;align-items:center}
.hd h1{font-size:28px;letter-spacing:-.03em}.hd small{display:block;color:#7fb3a8;font-size:14px;margin-top:4px}
.seg{margin-left:auto;display:flex;background:#12302d;border-radius:14px;padding:5px;position:relative}
.seg b{font-size:14px;padding:10px 20px;border-radius:10px;position:relative;z-index:2;color:#7fb3a8}
.seg i{position:absolute;top:5px;left:5px;width:calc(50% - 5px);height:calc(100% - 10px);border-radius:10px;background:#14b8a6;animation:sl 8s infinite both}
@keyframes sl{0%,38%{transform:none}46%,86%{transform:translateX(100%)}94%,100%{transform:none}}
.s1{animation:c1 8s infinite both}.s2{animation:c2 8s infinite both}
@keyframes c1{0%,38%{color:#04201c}46%,86%{color:#7fb3a8}94%,100%{color:#04201c}}@keyframes c2{0%,38%{color:#7fb3a8}46%,86%{color:#04201c}94%,100%{color:#7fb3a8}}
.ch{position:absolute;left:56px;right:56px;top:140px;height:480px;background:#10282a;border-radius:24px}
.gl{position:absolute;left:70px;right:40px;height:1px;background:#1c403f}
.bars{position:absolute;left:90px;right:60px;bottom:60px;height:340px;display:flex;gap:22px;align-items:flex-end}
.bars i{flex:1;border-radius:10px 10px 4px 4px;background:linear-gradient(#2dd4bf,#0f766e);height:var(--a);animation:bar 8s infinite both;transform-origin:bottom}
@keyframes bar{0%,6%{height:0}22%,38%{height:var(--a)}50%,86%{height:var(--b)}96%,100%{height:var(--a)}}
.lb{position:absolute;left:90px;right:60px;bottom:26px;display:flex;gap:22px;font-size:13px;color:#7fb3a8}.lb span{flex:1;text-align:center}
.tp{position:absolute;left:44px;top:20px;font-size:40px;font-weight:800;letter-spacing:-.04em}.tp small{display:block;font-size:13px;color:#7fb3a8;font-weight:500;letter-spacing:0}
.n1{animation:n1 8s infinite both}@keyframes n1{0%,10%{--n:0}34%,38%{--n:284}52%,86%{--n:421}96%,100%{--n:284}}
</style></head><body><div class="stage"><div class="hd"><div><h1>Revenue by month</h1><small>Bars morph when you switch the range</small></div><div class="seg"><i></i><b class="s1">2025</b><b class="s2">2026</b></div></div>
<div class="ch"><div class="gl" style="top:90px"></div><div class="gl" style="top:170px"></div><div class="gl" style="top:250px"></div><div class="gl" style="top:330px"></div><div class="tp">$<span class="cnt n1"></span>k<small>Total</small></div><div class="bars"><i style="--a:40%;--b:62%;animation-delay:0.0s"></i><i style="--a:58%;--b:44%;animation-delay:0.04s"></i><i style="--a:46%;--b:70%;animation-delay:0.08s"></i><i style="--a:72%;--b:58%;animation-delay:0.12s"></i><i style="--a:64%;--b:86%;animation-delay:0.16s"></i><i style="--a:88%;--b:74%;animation-delay:0.2s"></i><i style="--a:70%;--b:92%;animation-delay:0.24s"></i><i style="--a:52%;--b:64%;animation-delay:0.28s"></i></div><div class="lb"><span>Jan</span><span>Feb</span><span>Mar</span><span>Apr</span><span>May</span><span>Jun</span><span>Jul</span><span>Aug</span></div></div></div><script>window.start=function(){document.body.classList.add("go")};if(!/[?&]rec/.test(location.search))start();</script></body></html>
```