An accent cup pops under the espresso spout, fills, slides down the hairline counter past the grinder to the pickup mat and settles while two wisps of steam curl up.
Also known as: isometric coffee shop, coffee animation, hairline animation.
<div class="hln-coffee-counter" role="img" aria-label="A coffee cup is filled and slides along a counter to pickup"><svg viewBox="-36 -32.64 116 63.27" aria-hidden="true"><g><polygon points="-14,7 44,36 44,20 -14,-9"/><polygon points="58,29 44,36 44,20 58,13"/><polygon points="0,-16 58,13 44,20 -14,-9"/></g><line x1="-14" y1="4" x2="44" y2="33" class="hln-coffee-counter-l"/><line x1="-8" y1="7" x2="-8" y2="-4" class="hln-coffee-counter-l"/><line x1="5" y1="13.5" x2="5" y2="2.5" class="hln-coffee-counter-l"/><line x1="18" y1="20" x2="18" y2="9" class="hln-coffee-counter-l"/><line x1="31" y1="26.5" x2="31" y2="15.5" class="hln-coffee-counter-l"/><g><polygon points="-16,-9 44,21 44,19.5 -16,-10.5"/><polygon points="60,13 44,21 44,19.5 60,11.5"/><polygon points="0,-18.5 60,11.5 44,19.5 -16,-10.5"/></g><g><polygon points="-5.5,-11.75 11.5,-3.25 11.5,-16.25 -5.5,-24.75"/><polygon points="20,-7.5 11.5,-3.25 11.5,-16.25 20,-20.5"/><polygon points="3,-29 20,-20.5 11.5,-16.25 -5.5,-24.75"/></g><polygon class="hln-coffee-counter-l" points="3.5,-27.75 17.5,-20.75 11,-17.5 -3,-24.5"/><polygon points="-3.5,-19.75 9.5,-13.25 9.5,-15.75 -3.5,-22.25" class="hln-coffee-counter-l"/><g><polygon points="-0.2,-13.4 3.8,-11.4 3.8,-13.4 -0.2,-15.4"/><polygon points="6,-12.5 3.8,-11.4 3.8,-13.4 6,-14.5"/><polygon points="2,-16.5 6,-14.5 3.8,-13.4 -0.2,-15.4"/></g><g><polygon points="-6,-7.5 5,-2 5,-3 -6,-8.5"/><polygon points="9.5,-4.25 5,-2 5,-3 9.5,-5.25"/><polygon points="-1.5,-10.75 9.5,-5.25 5,-3 -6,-8.5"/></g><g><polygon points="15.5,-2.25 21.5,0.75 21.5,-7.25 15.5,-10.25"/><polygon points="27.5,-2.25 21.5,0.75 21.5,-7.25 27.5,-10.25"/><polygon points="21.5,-13.25 27.5,-10.25 21.5,-7.25 15.5,-10.25"/></g><path d="M17.26,-14.75 L18.67,-10.25 A2.83,1.41 0 0 0 24.33,-10.25 L25.74,-14.75 Z"/><ellipse cx="21.5" cy="-14.75" rx="4.24" ry="2.12"/><path d="M46.89,8.9 L47.17,10.5 A2.83,1.41 0 0 0 52.83,10.5 L53.11,8.9 Z"/><ellipse cx="50" cy="8.9" rx="3.11" ry="1.56"/><path d="M46.89,7.5 L47.17,9.1 A2.83,1.41 0 0 0 52.83,9.1 L53.11,7.5 Z"/><ellipse cx="50" cy="7.5" rx="3.11" ry="1.56"/><path d="M46.89,6.1 L47.17,7.7 A2.83,1.41 0 0 0 52.83,7.7 L53.11,6.1 Z"/><ellipse cx="50" cy="6.1" rx="3.11" ry="1.56"/><path d="M46.89,4.7 L47.17,6.3 A2.83,1.41 0 0 0 52.83,6.3 L53.11,4.7 Z"/><ellipse cx="50" cy="4.7" rx="3.11" ry="1.56"/><polygon class="hln-coffee-counter-l" points="36,7.5 45,12 39,15 30,10.5"/><g class="hln-coffee-counter-pour"><line x1="2.9" y1="-12.95" x2="2.9" y2="-10.85"/></g><g class="hln-coffee-counter-slide"><g class="hln-coffee-counter-cup"><polygon points="5.6,-7.2 5.57,-7.48 5.48,-7.78 5.34,-8.08 5.15,-8.36 4.92,-8.62 4.67,-8.84 4.4,-9 4.13,-9.1 3.88,-9.14 3.65,-9.11 3.46,-9.02 3.32,-8.86 3.23,-8.65 3.2,-8.4 3.23,-8.12 3.32,-7.82 3.46,-7.52 3.65,-7.24 3.88,-6.98 4.13,-6.76 4.4,-6.6 4.67,-6.5 4.92,-6.46 5.15,-6.49 5.34,-6.58 5.48,-6.74 5.57,-6.95" fill="none"/><path d="M-1.25,-10.4 L-0.69,-7 A2.69,1.34 0 0 0 4.69,-7 L5.25,-10.4 Z" class="hln-coffee-counter-a"/><ellipse cx="2" cy="-10.4" rx="3.25" ry="1.63"/><ellipse cx="2" cy="-10.4" rx="2.26" ry="1.13" class="hln-coffee-counter-l"/></g></g><path class="hln-coffee-counter-steam" style="--delay: 0s" fill="none" d="M34.8,5.6 c-1.6,-2 1.6,-3.5 0,-5.5 s1.6,-3.5 0,-5.5"/><path class="hln-coffee-counter-steam" style="--delay: -0.35s" fill="none" d="M37.4,5.6 c-1.6,-2 1.6,-3.5 0,-5.5 s1.6,-3.5 0,-5.5"/></svg></div>
.hln-coffee-counter {
--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;
--u: 1px;
}
.hln-coffee-counter svg {
width: 100%;
height: 100%;
overflow: visible;
fill: #ffffff;
stroke: #1c1d21;
stroke-width: 1.25;
stroke-linejoin: round;
stroke-linecap: round;
}
.hln-coffee-counter svg * {
vector-effect: non-scaling-stroke;
}
.hln-coffee-counter-l {
stroke: #9a9ca3;
}
.hln-coffee-counter-a {
fill: var(--c);
}
.hln-coffee-counter-steam {
stroke: #9a9ca3;
animation: hln-coffee-counter-steam 6s linear infinite;
animation-delay: var(--delay);
}
.hln-coffee-counter-slide {
animation: hln-coffee-counter-slide 6s linear infinite;
}
.hln-coffee-counter-cup {
transform-box: fill-box;
transform-origin: 50% 100%;
animation: hln-coffee-counter-cup 6s linear infinite;
}
.hln-coffee-counter-pour {
transform-box: fill-box;
transform-origin: 50% 0;
animation: hln-coffee-counter-pour 6s linear infinite;
}
@keyframes hln-coffee-counter-cup {
0% { transform: scale(0); opacity: 1; animation-timing-function: cubic-bezier(.3, 1.45, .5, 1); }
7%, 88% { transform: scale(1); opacity: 1; animation-timing-function: ease-in; }
96%, 100% { transform: scale(1); opacity: 0; }
}
@keyframes hln-coffee-counter-pour {
0%, 9% { transform: scaleY(0); opacity: 1; animation-timing-function: cubic-bezier(.22, 1, .36, 1); }
13%, 32% { transform: scaleY(1); opacity: 1; animation-timing-function: ease-in; }
36%, 100% { transform: scaleY(1); opacity: 0; }
}
@keyframes hln-coffee-counter-slide {
0%, 38% { transform: translate(calc(var(--u) * 0), calc(var(--u) * 0)); animation-timing-function: cubic-bezier(.45, 0, .2, 1.12); }
56%, 100% { transform: translate(calc(var(--u) * 34), calc(var(--u) * 17)); }
}
@keyframes hln-coffee-counter-steam {
0%, 56% { opacity: 0; transform: translate(calc(var(--u) * 0), calc(var(--u) * 0)); animation-timing-function: ease-out; }
66% { opacity: 1; transform: translate(calc(var(--u) * 0), calc(var(--u) * -1.5)); animation-timing-function: linear; }
86% { opacity: 0.8; transform: translate(calc(var(--u) * 0), calc(var(--u) * -4)); animation-timing-function: ease-in; }
94%, 100% { opacity: 0; transform: translate(calc(var(--u) * 0), calc(var(--u) * -5)); }
}
@media (prefers-reduced-motion: reduce) {
.hln-coffee-counter * {
animation-play-state: paused !important;
animation-delay: calc(var(--delay, 0s) - 4.5s) !important;
}
}
@media (prefers-reduced-motion: reduce) {
.hln-coffee-counter, .hln-coffee-counter *, .hln-coffee-counter::before, .hln-coffee-counter::after, .hln-coffee-counter *::before, .hln-coffee-counter *::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.