AI CSS Animations

Coffee Bar Pour and Pickup

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.

HTML

<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>

CSS

.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;
  }
}

Customizing this snippet

  • Color: set --hln-color on the element or a parent. Currently previewing #3b82f6.
  • Base size: set --hln-size. Every other dimension is in em, so the whole thing scales together. Currently previewing 16px.
  • Speed: change the duration on the transition or animation shorthand. Staggered delays are relative, so they keep their rhythm.
  • Reduced motion: the rule at the end of the CSS turns the motion off for people who asked their OS for less of it. Keep it.

Similar hairline animations