A hairline isometric power bank: a USB-C plug slides into the port on a spring, then four charge lights fill one after another, the last in the accent. The plug tip stretches out of the port exactly.
Also known as: hairline animation, isometric battery animation, charging animation css, power bank charging.
<div class="hln-battery-charge" role="img" aria-label="A power bank charging">
<svg viewBox="-110 -60 220 120" aria-hidden="true">
<g transform="translate(-19 -28.8) scale(1.15)">
<g><polygon points="-31.07,8 -30.94,7.31 -30.53,6.65 -29.88,6.04 -29,5.5 -5,-6.5 -3.93,-6.94 -2.71,-7.27 -1.38,-7.47 0,-7.54 1.38,-7.47 2.71,-7.27 3.93,-6.94 5,-6.5 57,19.5 57.88,20.04 58.53,20.65 58.94,21.31 59.07,22 59.07,31 58.94,31.69 58.53,32.35 57.88,32.96 57,33.5 33,45.5 31.93,45.94 30.71,46.27 29.38,46.47 28,46.54 26.62,46.47 25.29,46.27 24.07,45.94 23,45.5 -29,19.5 -29.88,18.96 -30.53,18.35 -30.94,17.69 -31.07,17"/><polygon points="57,19.5 57.88,20.04 58.53,20.65 58.94,21.31 59.07,22 58.94,22.69 58.53,23.35 57.88,23.96 57,24.5 33,36.5 31.93,36.94 30.71,37.27 29.38,37.47 28,37.54 26.62,37.47 25.29,37.27 24.07,36.94 23,36.5 -29,10.5 -29.88,9.96 -30.53,9.35 -30.94,8.69 -31.07,8 -30.94,7.31 -30.53,6.65 -29.88,6.04 -29,5.5 -5,-6.5 -3.93,-6.94 -2.71,-7.27 -1.38,-7.47 0,-7.54 1.38,-7.47 2.71,-7.27 3.93,-6.94 5,-6.5"/></g>
<polygon class="hln-battery-charge-l" points="19,6.5 19.53,6.82 19.92,7.19 20.16,7.59 20.24,8 20.16,8.41 19.92,8.81 19.53,9.18 19,9.5 3,17.5 2.36,17.76 1.62,17.96 0.83,18.08 0,18.12 -0.83,18.08 -1.62,17.96 -2.36,17.76 -3,17.5 -19,9.5 -19.53,9.18 -19.92,8.81 -20.16,8.41 -20.24,8 -20.16,7.59 -19.92,7.19 -19.53,6.82 -19,6.5 -3,-1.5 -2.36,-1.76 -1.62,-1.96 -0.83,-2.08 0,-2.12 0.83,-2.08 1.62,-1.96 2.36,-1.76 3,-1.5"/>
<ellipse class="hln-battery-charge-l" cx="12" cy="25" rx="1.56" ry="0.78"/><g class="hln-battery-charge-led" style="--i: 0"><ellipse class="hln-battery-charge-k" cx="12" cy="25" rx="1.56" ry="0.78"/></g><ellipse class="hln-battery-charge-l" cx="17" cy="27.5" rx="1.56" ry="0.78"/><g class="hln-battery-charge-led" style="--i: 1"><ellipse class="hln-battery-charge-k" cx="17" cy="27.5" rx="1.56" ry="0.78"/></g><ellipse class="hln-battery-charge-l" cx="22" cy="30" rx="1.56" ry="0.78"/><g class="hln-battery-charge-led" style="--i: 2"><ellipse class="hln-battery-charge-k" cx="22" cy="30" rx="1.56" ry="0.78"/></g><ellipse class="hln-battery-charge-l" cx="27" cy="32.5" rx="1.56" ry="0.78"/><g class="hln-battery-charge-led" style="--i: 3"><ellipse class="hln-battery-charge-af" cx="27" cy="32.5" rx="1.56" ry="0.78"/></g>
<g transform="matrix(1 -.5 0 -1 28 48)"><rect class="hln-battery-charge-l" x="13.5" y="3.2" width="7" height="2.6" rx="1.3"/></g>
<g transform="matrix(1 .5 -1 .5 47.4 32.5)"><rect class="hln-battery-charge-s" x="0" y="0" width="1" height="4.8"/></g>
<g transform="matrix(1 .5 0 -1 42.6 37.5)"><rect class="hln-battery-charge-s" x="0" y="0" width="1" height="2.6"/></g>
<g class="hln-battery-charge-plug"><g><polygon points="40.5,39.75 49.5,44.25 49.5,39.25 40.5,34.75"/><polygon points="58.5,39.75 49.5,44.25 49.5,39.25 58.5,34.75"/><polygon points="49.5,30.25 58.5,34.75 49.5,39.25 40.5,34.75"/></g><g transform="matrix(1 -.5 0 -1 49.5 44.25)"><rect class="hln-battery-charge-l" x="2.5" y="1.6" width="4" height="1.8" rx="0.9"/></g><path class="hln-battery-charge-o" d="M54,39.5 L61,43 Q67,46 61,49 L44,57.5"/></g>
</g>
</svg>
</div>.hln-battery-charge {
--c: var(--hln-color, #ff4f2e);
font-size: var(--hln-size, 16px);
position: relative;
display: grid;
place-items: center;
width: 22em;
height: 12em;
border-radius: 0.75em;
background: #f6f5f1;
overflow: hidden;
}
.hln-battery-charge svg {
width: 100%;
height: 100%;
overflow: visible;
fill: #ffffff;
stroke: #1c1d21;
stroke-width: 1.25;
stroke-linejoin: round;
stroke-linecap: round;
}
.hln-battery-charge svg * {
vector-effect: non-scaling-stroke;
}
.hln-battery-charge .hln-battery-charge-o {
fill: none;
}
.hln-battery-charge .hln-battery-charge-l {
stroke: #9a9ca3;
}
.hln-battery-charge .hln-battery-charge-k {
fill: #1c1d21;
}
.hln-battery-charge .hln-battery-charge-af {
fill: var(--c);
stroke: var(--c);
}
@property --hln-battery-charge-o {
syntax: "<number>";
inherits: true;
initial-value: 0;
}
.hln-battery-charge svg {
animation: hln-battery-charge-plug 6s infinite;
}
.hln-battery-charge .hln-battery-charge-s {
transform: matrix(min(var(--hln-battery-charge-o), 5), 0, 0, 1, max(0, var(--hln-battery-charge-o) - 5), 0);
}
.hln-battery-charge .hln-battery-charge-plug {
transform: matrix(1, 0, 0, 1, var(--hln-battery-charge-o), calc(var(--hln-battery-charge-o) / 2));
}
.hln-battery-charge .hln-battery-charge-led {
animation: hln-battery-charge-led 6s calc(var(--i) * 0.45s) infinite both;
}
@keyframes hln-battery-charge-plug {
0% { --hln-battery-charge-o: 12; }
8.33% { --hln-battery-charge-o: 12; animation-timing-function: linear(0, 0.035, 0.125, 0.247, 0.384, 0.524, 0.655, 0.771, 0.87, 0.948, 1.008, 1.05, 1.077, 1.091, 1.095, 1.091, 1.083, 1.071, 1.058, 1.045, 1.032, 1.021, 1.012, 1.005, 0.999, 0.995, 0.993, 0.991, 0.991, 0.991, 0.992, 0.993, 1); }
23.33% { --hln-battery-charge-o: 0; }
81.67% { --hln-battery-charge-o: 0; animation-timing-function: cubic-bezier(.65,0,.35,1); }
91.67% { --hln-battery-charge-o: 12; }
100% { --hln-battery-charge-o: 12; }
}
@keyframes hln-battery-charge-led {
0% { opacity: 0; }
25% { opacity: 0; }
28.33% { opacity: 1; }
78.33% { opacity: 1; }
81.67% { opacity: 0; }
100% { opacity: 0; }
}
@media (prefers-reduced-motion: reduce) {
.hln-battery-charge * {
animation: none !important;
}
}
@media (prefers-reduced-motion: reduce) {
.hln-battery-charge, .hln-battery-charge *, .hln-battery-charge::before, .hln-battery-charge::after, .hln-battery-charge *::before, .hln-battery-charge *::after {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
}
}--hln-color on the element or a parent.
Currently previewing #3b82f6.--hln-size. Every other dimension is in
em, so the whole thing scales together. Currently previewing 16px.transition or animation
shorthand. Staggered delays are relative, so they keep their rhythm.