AI CSS Animations

Sorting Belt Diverter

White boxes ride a conveyor while a pusher fires on the accent box, shoving it off the belt down a chute into a bin. Inline SVG with layered copies so every hand-off keeps its depth.

Also known as: isometric conveyor belt animation, package sorting animation, hairline animation.

HTML

<div class="hln-sorting-belt" role="img" aria-label="A pusher diverts one box from a conveyor belt into a bin"><svg viewBox="-40 -31.82 168 91.64" aria-hidden="true"><polygon points="63,-0.5 81,8.5 65,16.5 47,7.5"/><polygon points="63,-0.5 81,8.5 81,1.5 63,-7.5"/><polygon points="63,-0.5 47,7.5 47,0.5 63,-7.5"/><g class="hln-sorting-belt-path"><g class="hln-sorting-belt-in"><g class="hln-sorting-belt-a"><polygon points="-8,-8 -1,-4.5 -1,-9.5 -8,-13"/><polygon points="5,-7.5 -1,-4.5 -1,-9.5 5,-12.5"/><polygon points="-2,-16 5,-12.5 -1,-9.5 -8,-13"/></g></g></g><polygon points="47,7.5 65,16.5 65,9.5 47,0.5"/><polygon points="81,8.5 65,16.5 65,9.5 81,1.5"/><polygon points="47,1 64,9.5 80.5,1.25 63.5,-7.25" class="hln-sorting-belt-l" fill="none"/><polygon points="33,5 47,12 63,8 49,1"/><line x1="40" y1="8.5" x2="56" y2="4.5" class="hln-sorting-belt-l"/><g class="hln-sorting-belt-path"><g class="hln-sorting-belt-mid"><g class="hln-sorting-belt-a"><polygon points="-8,-8 -1,-4.5 -1,-9.5 -8,-13"/><polygon points="5,-7.5 -1,-4.5 -1,-9.5 5,-12.5"/><polygon points="-2,-16 5,-12.5 -1,-9.5 -8,-13"/></g></g></g><line x1="3" y1="1.5" x2="3" y2="-8.5"/><line x1="42" y1="21" x2="42" y2="11"/><line x1="81" y1="40.5" x2="81" y2="30.5"/><g><polygon points="-10,-5 74,37 74,35 -10,-7"/><polygon points="84,32 74,37 74,35 84,30"/><polygon points="0,-12 84,30 74,35 -10,-7"/></g><line x1="3" y1="-10.5" x2="-7" y2="-5.5" class="hln-sorting-belt-l"/><line x1="6.5" y1="-8.75" x2="-3.5" y2="-3.75" class="hln-sorting-belt-l"/><line x1="10" y1="-7" x2="0" y2="-2" class="hln-sorting-belt-l"/><line x1="13.5" y1="-5.25" x2="3.5" y2="-0.25" class="hln-sorting-belt-l"/><line x1="17" y1="-3.5" x2="7" y2="1.5" class="hln-sorting-belt-l"/><line x1="20.5" y1="-1.75" x2="10.5" y2="3.25" class="hln-sorting-belt-l"/><line x1="24" y1="0" x2="14" y2="5" class="hln-sorting-belt-l"/><line x1="27.5" y1="1.75" x2="17.5" y2="6.75" class="hln-sorting-belt-l"/><line x1="31" y1="3.5" x2="21" y2="8.5" class="hln-sorting-belt-l"/><line x1="34.5" y1="5.25" x2="24.5" y2="10.25" class="hln-sorting-belt-l"/><line x1="38" y1="7" x2="28" y2="12" class="hln-sorting-belt-l"/><line x1="41.5" y1="8.75" x2="31.5" y2="13.75" class="hln-sorting-belt-l"/><line x1="45" y1="10.5" x2="35" y2="15.5" class="hln-sorting-belt-l"/><line x1="48.5" y1="12.25" x2="38.5" y2="17.25" class="hln-sorting-belt-l"/><line x1="52" y1="14" x2="42" y2="19" class="hln-sorting-belt-l"/><line x1="55.5" y1="15.75" x2="45.5" y2="20.75" class="hln-sorting-belt-l"/><line x1="59" y1="17.5" x2="49" y2="22.5" class="hln-sorting-belt-l"/><line x1="62.5" y1="19.25" x2="52.5" y2="24.25" class="hln-sorting-belt-l"/><line x1="66" y1="21" x2="56" y2="26" class="hln-sorting-belt-l"/><line x1="69.5" y1="22.75" x2="59.5" y2="27.75" class="hln-sorting-belt-l"/><line x1="73" y1="24.5" x2="63" y2="29.5" class="hln-sorting-belt-l"/><line x1="76.5" y1="26.25" x2="66.5" y2="31.25" class="hln-sorting-belt-l"/><line x1="80" y1="28" x2="70" y2="33" class="hln-sorting-belt-l"/><line x1="83.5" y1="29.75" x2="73.5" y2="34.75" class="hln-sorting-belt-l"/><line x1="-7" y1="6.5" x2="-7" y2="-3.5"/><line x1="71" y1="45.5" x2="71" y2="35.5"/><g class="hln-sorting-belt-w" style="--delay: -1.5s"><g><polygon points="-8,-8 -1,-4.5 -1,-9.5 -8,-13"/><polygon points="5,-7.5 -1,-4.5 -1,-9.5 5,-12.5"/><polygon points="-2,-16 5,-12.5 -1,-9.5 -8,-13"/></g><line x1="-5" y1="-14.5" x2="2" y2="-11" class="hln-sorting-belt-l"/></g><g class="hln-sorting-belt-w" style="--delay: -4.5s"><g><polygon points="-8,-8 -1,-4.5 -1,-9.5 -8,-13"/><polygon points="5,-7.5 -1,-4.5 -1,-9.5 5,-12.5"/><polygon points="-2,-16 5,-12.5 -1,-9.5 -8,-13"/></g><line x1="-5" y1="-14.5" x2="2" y2="-11" class="hln-sorting-belt-l"/></g><g class="hln-sorting-belt-path"><g class="hln-sorting-belt-top"><g class="hln-sorting-belt-a"><polygon points="-8,-8 -1,-4.5 -1,-9.5 -8,-13"/><polygon points="5,-7.5 -1,-4.5 -1,-9.5 5,-12.5"/><polygon points="-2,-16 5,-12.5 -1,-9.5 -8,-13"/></g></g></g><g class="hln-sorting-belt-push"><g><polygon points="20,11.5 31,17 31,13 20,7.5"/><polygon points="32.5,16.25 31,17 31,13 32.5,12.25"/><polygon points="21.5,6.75 32.5,12.25 31,13 20,7.5"/></g><g><polygon points="15.5,17.25 17.5,18.25 17.5,16.25 15.5,15.25"/><polygon points="26.5,13.75 17.5,18.25 17.5,16.25 26.5,11.75"/><polygon points="24.5,10.75 26.5,11.75 17.5,16.25 15.5,15.25"/></g></g><line x1="7" y1="29.5" x2="7" y2="17.5"/><line x1="21" y1="36.5" x2="21" y2="24.5"/><line x1="31" y1="31.5" x2="31" y2="19.5"/><g><polygon points="5,17.5 21,25.5 21,19.5 5,11.5"/><polygon points="33,19.5 21,25.5 21,19.5 33,13.5"/><polygon points="17,5.5 33,13.5 21,19.5 5,11.5"/></g><polygon points="8,17 12,19 12,17 8,15" class="hln-sorting-belt-l"/><line x1="14" y1="19" x2="18" y2="21" class="hln-sorting-belt-l"/></svg></div>

CSS

.hln-sorting-belt {
  --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-sorting-belt svg {
  width: 100%;
  height: 100%;
  overflow: visible;
  fill: #ffffff;
  stroke: #1c1d21;
  stroke-width: 1.25;
  stroke-linejoin: round;
  stroke-linecap: round;
}
.hln-sorting-belt svg * {
  vector-effect: non-scaling-stroke;
}
.hln-sorting-belt-l {
  stroke: #9a9ca3;
}
.hln-sorting-belt-a {
  fill: var(--c);
}
.hln-sorting-belt-path {
  animation: hln-sorting-belt-path 6s linear infinite;
}
.hln-sorting-belt-top {
  animation: hln-sorting-belt-top 6s linear infinite;
}
.hln-sorting-belt-mid {
  animation: hln-sorting-belt-mid 6s linear infinite;
}
.hln-sorting-belt-in {
  animation: hln-sorting-belt-in 6s linear infinite;
}
.hln-sorting-belt-w {
  animation: hln-sorting-belt-w 6s linear infinite;
  animation-delay: var(--delay);
}
.hln-sorting-belt-push {
  animation: hln-sorting-belt-push 6s linear infinite;
}
@keyframes hln-sorting-belt-path {
  0% { transform: translate(calc(var(--u) * 0), calc(var(--u) * 0)); }
  49% { transform: translate(calc(var(--u) * 38), calc(var(--u) * 19)); animation-timing-function: cubic-bezier(.4, 0, .2, 1); }
  52% { transform: translate(calc(var(--u) * 38), calc(var(--u) * 19)); animation-timing-function: cubic-bezier(.3, 0, .2, 1); }
  58% { transform: translate(calc(var(--u) * 46), calc(var(--u) * 15)); animation-timing-function: cubic-bezier(.45, 0, .8, .5); }
  66% { transform: translate(calc(var(--u) * 56), calc(var(--u) * 14)); animation-timing-function: cubic-bezier(.5, 0, .8, .4); }
  71% { transform: translate(calc(var(--u) * 62), calc(var(--u) * 19)); animation-timing-function: cubic-bezier(.3, 1.45, .5, 1); }
  76%, 100% { transform: translate(calc(var(--u) * 62), calc(var(--u) * 19)); }
}
@keyframes hln-sorting-belt-top {
  0% { opacity: 0; }
  5%, 57.9% { opacity: 1; }
  58%, 100% { opacity: 0; }
}
@keyframes hln-sorting-belt-mid {
  0%, 57.9% { opacity: 0; }
  58%, 67.9% { opacity: 1; }
  68%, 100% { opacity: 0; }
}
@keyframes hln-sorting-belt-in {
  0%, 67.9% { opacity: 0; }
  68%, 88% { opacity: 1; }
  96%, 100% { opacity: 0; }
}
@keyframes hln-sorting-belt-w {
  0% { opacity: 0; transform: translate(calc(var(--u) * 0), calc(var(--u) * 0)); }
  5% { opacity: 1; transform: translate(calc(var(--u) * 3.85), calc(var(--u) * 1.93)); }
  95% { opacity: 1; transform: translate(calc(var(--u) * 73.15), calc(var(--u) * 36.57)); }
  100% { opacity: 0; transform: translate(calc(var(--u) * 77), calc(var(--u) * 38.5)); }
}
@keyframes hln-sorting-belt-push {
  0%, 48% { transform: translate(calc(var(--u) * 0), calc(var(--u) * 0)); animation-timing-function: cubic-bezier(.5, 0, .9, .5); }
  52% { transform: translate(calc(var(--u) * 5), calc(var(--u) * -2.5)); animation-timing-function: cubic-bezier(.3, 0, .2, 1); }
  58% { transform: translate(calc(var(--u) * 13), calc(var(--u) * -6.5)); animation-timing-function: cubic-bezier(.3, 1.45, .5, 1); }
  60%, 64% { transform: translate(calc(var(--u) * 12), calc(var(--u) * -6)); animation-timing-function: cubic-bezier(.65, 0, .35, 1); }
  74%, 100% { transform: translate(calc(var(--u) * 0), calc(var(--u) * 0)); }
}
@media (prefers-reduced-motion: reduce) {
  .hln-sorting-belt * {
    animation-play-state: paused !important;
    animation-delay: calc(var(--delay, 0s) - 4.6s) !important;
  }
}

@media (prefers-reduced-motion: reduce) {
  .hln-sorting-belt, .hln-sorting-belt *, .hln-sorting-belt::before, .hln-sorting-belt::after, .hln-sorting-belt *::before, .hln-sorting-belt *::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