A request packet crosses from an isometric browser window to a server rack, a status light blinks, and the response returns to draw the page. SVG with CSS translate and dashes.
Also known as: api request animation, client server animation, hairline isometric.
<div class="hln-api-round-trip" role="img" aria-label="An API request travelling to a server and back"> <svg viewBox="-110 -60 220 120" aria-hidden="true"><g transform="translate(0 12) scale(1.45)"><g><polygon points="-45,-21.5 -19,-8.5 -19,-28.5 -45,-41.5"/><polygon points="-16,-10 -19,-8.5 -19,-28.5 -16,-30"/><polygon points="-42,-43 -16,-30 -19,-28.5 -45,-41.5"/></g><polygon class="hln-api-round-trip-in" points="-43,-22.5 -21,-11.5 -21,-24.5 -43,-35.5"/><polygon class="hln-api-round-trip-in" points="-42,-36.6 -41,-36.1 -41,-37.1 -42,-37.6"/><polygon class="hln-api-round-trip-in" points="-40,-35.6 -39,-35.1 -39,-36.1 -40,-36.6"/><polygon class="hln-api-round-trip-in" points="-38,-34.6 -37,-34.1 -37,-35.1 -38,-35.6"/><line class="hln-api-round-trip-text" style="transform-origin: 0% 0%" x1="-41" y1="-31.5" x2="-25" y2="-23.5"/><line class="hln-api-round-trip-text hln-api-round-trip-t1" style="transform-origin: 0% 0%" x1="-41" y1="-28.5" x2="-31" y2="-23.5"/><line class="hln-api-round-trip-text hln-api-round-trip-t2" style="transform-origin: 0% 0%" x1="-41" y1="-25.5" x2="-28" y2="-19"/><line class="hln-api-round-trip-in" x1="-17.5" y1="-19.25" x2="16.5" y2="-2.25"/><g class="hln-api-round-trip-move"><g class="hln-api-round-trip-pkt"><g><polygon points="-3.5,-8.25 0.5,-6.25 0.5,-10.25 -3.5,-12.25"/><polygon points="4.5,-8.25 0.5,-6.25 0.5,-10.25 4.5,-12.25"/><polygon points="0.5,-14.25 4.5,-12.25 0.5,-10.25 -3.5,-12.25"/></g></g></g><g><polygon points="10,11 24,18 24,-10 10,-17"/><polygon points="38,11 24,18 24,-10 38,-17"/><polygon points="24,-24 38,-17 24,-10 10,-17"/></g><line class="hln-api-round-trip-in" x1="10" y1="4" x2="24" y2="11"/><line class="hln-api-round-trip-in" x1="10" y1="-3" x2="24" y2="4"/><line class="hln-api-round-trip-in" x1="10" y1="-10" x2="24" y2="-3"/><polygon class="hln-api-round-trip-in" points="12,9.4 14,10.4 14,8.6 12,7.6"/><polygon class="hln-api-round-trip-in" points="12,2.4 14,3.4 14,1.6 12,0.6"/><polygon class="hln-api-round-trip-in" points="12,-4.6 14,-3.6 14,-5.4 12,-6.4"/><polygon class="hln-api-round-trip-led" points="12,-11.6 14,-10.6 14,-12.4 12,-13.4"/></g></svg> </div>
.hln-api-round-trip {
--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-api-round-trip svg {
width: 100%;
height: 100%;
overflow: visible;
fill: #ffffff;
stroke: #1c1d21;
stroke-width: 1.25;
stroke-linejoin: round;
stroke-linecap: round;
}
.hln-api-round-trip svg * {
vector-effect: non-scaling-stroke;
}
.hln-api-round-trip .hln-api-round-trip-in {
stroke: #9a9ca3;
}
.hln-api-round-trip .hln-api-round-trip-move {
translate: calc(-15 * var(--u)) calc(-7.5 * var(--u));
animation: hln-api-round-trip-move 6s infinite;
}
.hln-api-round-trip .hln-api-round-trip-pkt {
transform-box: fill-box;
transform-origin: 50% 50%;
animation: hln-api-round-trip-pkt 6s infinite;
}
.hln-api-round-trip .hln-api-round-trip-pkt polygon {
fill: var(--c);
}
.hln-api-round-trip .hln-api-round-trip-led {
fill: #ffffff;
animation: hln-api-round-trip-led 6s infinite;
}
.hln-api-round-trip .hln-api-round-trip-text {
transform-box: fill-box;
scale: 0 1;
animation: hln-api-round-trip-text 6s infinite;
}
.hln-api-round-trip .hln-api-round-trip-t1 {
animation-delay: 0.12s;
}
.hln-api-round-trip .hln-api-round-trip-t2 {
animation-delay: 0.24s;
}
@keyframes hln-api-round-trip-move {
0% { translate: calc(-15 * var(--u)) calc(-7.5 * var(--u)); }
9% { translate: calc(-15 * var(--u)) calc(-7.5 * var(--u)); animation-timing-function: cubic-bezier(0.65, 0, 0.35, 1); }
29% { translate: calc(13 * var(--u)) calc(6.5 * var(--u)); }
49% { translate: calc(13 * var(--u)) calc(6.5 * var(--u)); animation-timing-function: cubic-bezier(0.65, 0, 0.35, 1); }
69% { translate: calc(-15 * var(--u)) calc(-7.5 * var(--u)); }
100% { translate: calc(-15 * var(--u)) calc(-7.5 * var(--u)); }
}
@keyframes hln-api-round-trip-pkt {
0%, 2% { scale: 0; animation-timing-function: cubic-bezier(0.3, 1.45, 0.45, 1); }
9%, 29% { scale: 1; animation-timing-function: ease-in; }
33%, 42% { scale: 0; animation-timing-function: cubic-bezier(0.3, 1.45, 0.45, 1); }
49%, 69% { scale: 1; animation-timing-function: ease-in; }
73%, 100% { scale: 0; }
}
@keyframes hln-api-round-trip-led {
0%, 31% { fill: #ffffff; }
33%, 44% { fill: var(--c); }
52%, 100% { fill: #ffffff; }
}
@keyframes hln-api-round-trip-text {
0%, 71% { scale: 0 1; opacity: 1; animation-timing-function: cubic-bezier(0.22, 1, 0.36, 1); }
80%, 90% { scale: 1; opacity: 1; }
97%, 100% { scale: 1; opacity: 0; }
}
@media (prefers-reduced-motion: reduce) {
.hln-api-round-trip * {
animation: none !important;
}
.hln-api-round-trip .hln-api-round-trip-text { scale: 1; }
.hln-api-round-trip .hln-api-round-trip-move { translate: calc(-1 * var(--u)) calc(-0.5 * var(--u)); }
}
@media (prefers-reduced-motion: reduce) {
.hln-api-round-trip, .hln-api-round-trip *, .hln-api-round-trip::before, .hln-api-round-trip::after, .hln-api-round-trip *::before, .hln-api-round-trip *::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.