AI CSS Animations

Kanban Card Move

An accent card lifts off an isometric kanban board, glides from To do to Doing to Done and drops into place with a spring, then resets. Hairline SVG with CSS translate.

Also known as: kanban board animation, task board animation, hairline isometric.

HTML

<div class="hln-kanban-card-move" role="img" aria-label="A task card moving across a kanban board">
  <svg viewBox="-110 -60 220 120" aria-hidden="true"><g transform="translate(0 2) scale(1.55)"><g><polygon points="-54,-10 20,27 20,25 -54,-12"/><polygon points="54,10 20,27 20,25 54,8"/><polygon points="-20,-29 54,8 20,25 -54,-12"/></g><line class="hln-kanban-card-move-in" x1="3" y1="-15.5" x2="-27" y2="-0.5"/><line class="hln-kanban-card-move-in" x1="27" y1="-3.5" x2="-3" y2="11.5"/><line class="hln-kanban-card-move-in" x1="-20" y1="-25" x2="-12" y2="-21"/><line class="hln-kanban-card-move-in" x1="4" y1="-13" x2="12" y2="-9"/><line class="hln-kanban-card-move-in" x1="28" y1="-1" x2="36" y2="3"/><g><g><polygon points="-32,-19 -14,-10 -14,-11.5 -32,-20.5"/><polygon points="-5,-14.5 -14,-10 -14,-11.5 -5,-16"/><polygon points="-23,-25 -5,-16 -14,-11.5 -32,-20.5"/></g><line class="hln-kanban-card-move-in" x1="-23" y1="-22" x2="-13" y2="-17"/><line class="hln-kanban-card-move-in" x1="-26" y1="-20.5" x2="-20" y2="-17.5"/></g><g><g><polygon points="-8,-7 10,2 10,0.5 -8,-8.5"/><polygon points="19,-2.5 10,2 10,0.5 19,-4"/><polygon points="1,-13 19,-4 10,0.5 -8,-8.5"/></g><line class="hln-kanban-card-move-in" x1="1" y1="-10" x2="11" y2="-5"/><line class="hln-kanban-card-move-in" x1="-2" y1="-8.5" x2="4" y2="-5.5"/></g><g><g><polygon points="16,5 34,14 34,12.5 16,3.5"/><polygon points="43,9.5 34,14 34,12.5 43,8"/><polygon points="25,-1 43,8 34,12.5 16,3.5"/></g><line class="hln-kanban-card-move-in" x1="25" y1="2" x2="35" y2="7"/><line class="hln-kanban-card-move-in" x1="22" y1="3.5" x2="28" y2="6.5"/></g><g class="hln-kanban-card-move-move"><g><polygon points="-43,-13.5 -25,-4.5 -25,-6 -43,-15"/><polygon points="-16,-9 -25,-4.5 -25,-6 -16,-10.5"/><polygon points="-34,-19.5 -16,-10.5 -25,-6 -43,-15"/></g></g></g></svg>
</div>

CSS

.hln-kanban-card-move {
  --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-kanban-card-move svg {
  width: 100%;
  height: 100%;
  overflow: visible;
  fill: #ffffff;
  stroke: #1c1d21;
  stroke-width: 1.25;
  stroke-linejoin: round;
  stroke-linecap: round;
}
.hln-kanban-card-move svg * {
  vector-effect: non-scaling-stroke;
}
.hln-kanban-card-move .hln-kanban-card-move-in {
  stroke: #9a9ca3;
}
.hln-kanban-card-move .hln-kanban-card-move-move {
  animation: hln-kanban-card-move-move 6.4s infinite;
}
.hln-kanban-card-move .hln-kanban-card-move-move > g > polygon:last-child {
  fill: var(--c);
}
@keyframes hln-kanban-card-move-move {
  0% { translate: 0 0; opacity: 0; }
  4% { translate: 0 0; opacity: 1; }
  10% { translate: 0 0; animation-timing-function: cubic-bezier(0.22, 1, 0.36, 1); }
  15% { translate: 0 calc(-5 * var(--u)); }
  16% { translate: 0 calc(-5 * var(--u)); animation-timing-function: cubic-bezier(0.65, 0, 0.35, 1); }
  30% { translate: calc(24 * var(--u)) calc(7 * var(--u)); }
  31% { translate: calc(24 * var(--u)) calc(7 * var(--u)); animation-timing-function: cubic-bezier(0.3, 0, 0.2, 1); }
  34.3% { translate: calc(24 * var(--u)) calc(12.4 * var(--u)); animation-timing-function: ease-in-out; }
  35.8% { translate: calc(24 * var(--u)) calc(11.9 * var(--u)); animation-timing-function: ease-in-out; }
  37% { translate: calc(24 * var(--u)) calc(12 * var(--u)); }
  50% { translate: calc(24 * var(--u)) calc(12 * var(--u)); animation-timing-function: cubic-bezier(0.22, 1, 0.36, 1); }
  55% { translate: calc(24 * var(--u)) calc(7 * var(--u)); }
  56% { translate: calc(24 * var(--u)) calc(7 * var(--u)); animation-timing-function: cubic-bezier(0.65, 0, 0.35, 1); }
  70% { translate: calc(48 * var(--u)) calc(19 * var(--u)); }
  71% { translate: calc(48 * var(--u)) calc(19 * var(--u)); animation-timing-function: cubic-bezier(0.3, 0, 0.2, 1); }
  74.3% { translate: calc(48 * var(--u)) calc(24.4 * var(--u)); animation-timing-function: ease-in-out; }
  75.8% { translate: calc(48 * var(--u)) calc(23.9 * var(--u)); animation-timing-function: ease-in-out; }
  77% { translate: calc(48 * var(--u)) calc(24 * var(--u)); }
  92% { translate: calc(48 * var(--u)) calc(24 * var(--u)); opacity: 1; }
  98%, 100% { translate: calc(48 * var(--u)) calc(24 * var(--u)); opacity: 0; }
}
@media (prefers-reduced-motion: reduce) {
  .hln-kanban-card-move * {
    animation: none !important;
  }
  .hln-kanban-card-move .hln-kanban-card-move-move { translate: calc(24 * var(--u)) calc(12 * var(--u)); }
}

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