AI CSS Animations

Agent Kanban Board

A three column board of agent tasks: cards lift and slide from Running to Review to Done, the column counts tick over and a fresh task drops into Running. One @property clock moves every card.

Also known as: ai agent task board, kanban card animation, agent task status board.

  • Rate limiterauth-ttl
  • Flaky e2eci-fixer
  • API docsdocs-sync
  • Bump eslintdeps-bot

HTML

<div class="aia-agent-kanban" role="status" aria-label="Agent tasks moving from Running to Review to Done">
  <div class="aia-agent-kanban-cols" aria-hidden="true">
    <div class="aia-agent-kanban-col"><span><i></i>Running</span><b class="aia-agent-kanban-n1"></b></div>
    <div class="aia-agent-kanban-col"><span><i></i>Review</span><b class="aia-agent-kanban-n2"></b></div>
    <div class="aia-agent-kanban-col"><span><i></i>Done</span><b class="aia-agent-kanban-n3"></b></div>
  </div>
  <ul class="aia-agent-kanban-cards">
    <li class="aia-agent-kanban-card aia-agent-kanban-a"><span class="aia-agent-kanban-st" aria-hidden="true"><i class="aia-agent-kanban-spin"></i><i class="aia-agent-kanban-wait"></i><svg class="aia-agent-kanban-ok" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m5.5 12.5 4 4 9-9.5"/></svg></span><b>Rate limiter</b><code>auth-ttl</code></li>
    <li class="aia-agent-kanban-card aia-agent-kanban-b"><span class="aia-agent-kanban-st" aria-hidden="true"><i class="aia-agent-kanban-spin"></i><i class="aia-agent-kanban-wait"></i><svg class="aia-agent-kanban-ok" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m5.5 12.5 4 4 9-9.5"/></svg></span><b>Flaky e2e</b><code>ci-fixer</code></li>
    <li class="aia-agent-kanban-card aia-agent-kanban-c"><span class="aia-agent-kanban-st" aria-hidden="true"><i class="aia-agent-kanban-spin"></i><i class="aia-agent-kanban-wait"></i><svg class="aia-agent-kanban-ok" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m5.5 12.5 4 4 9-9.5"/></svg></span><b>API docs</b><code>docs-sync</code></li>
    <li class="aia-agent-kanban-card aia-agent-kanban-d"><span class="aia-agent-kanban-st" aria-hidden="true"><i class="aia-agent-kanban-spin"></i><i class="aia-agent-kanban-wait"></i><svg class="aia-agent-kanban-ok" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m5.5 12.5 4 4 9-9.5"/></svg></span><b>Bump eslint</b><code>deps-bot</code></li>
  </ul>
</div>

CSS

@property --aia-agent-kanban-t {
  syntax: "<number>";
  inherits: true;
  initial-value: 0;
}
@property --aia-agent-kanban-c1 {
  syntax: "<integer>";
  inherits: false;
  initial-value: 0;
}
@property --aia-agent-kanban-c2 {
  syntax: "<integer>";
  inherits: false;
  initial-value: 0;
}
@property --aia-agent-kanban-c3 {
  syntax: "<integer>";
  inherits: false;
  initial-value: 0;
}
.aia-agent-kanban {
  --c: var(--aia-color, #7c5cff);
  font-size: var(--aia-size, 16px);
  font-family: system-ui, -apple-system, "Segoe UI", sans-serif;
  line-height: 1.4;
  position: relative;
  box-sizing: border-box;
  padding: 0.9em 1em;
  border-radius: 0.9em;
  background: color-mix(in srgb, currentColor 3%, transparent);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, currentColor 11%, transparent), 0 0.1em 0.2em color-mix(in srgb, currentColor 4%, transparent), 0 0.9em 2em -1.1em rgb(0 0 0 / 0.3);
  --d: 9s;
  --t: var(--aia-agent-kanban-t);
  --s1: clamp(0, var(--t), 1);
  --s2: clamp(0, var(--t) - 1, 1);
  --s3: clamp(0, var(--t) - 2, 1);
  --s4: clamp(0, var(--t) - 3, 1);
  --w: 7.6em;
  --gap: 0.45em;
  --ok: color-mix(in srgb, #16a34a 78%, currentColor);
  --wait: color-mix(in srgb, #d97706 84%, currentColor);
  padding: 0.6em;
  animation: aia-agent-kanban-clock var(--d) cubic-bezier(0.65, 0, 0.35, 1) infinite;
}
.aia-agent-kanban-cols {
  display: grid;
  grid-template-columns: repeat(3, var(--w));
  gap: var(--gap);
}
.aia-agent-kanban-col {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  box-sizing: border-box;
  height: 7.75em;
  padding: 0.5em 0.55em;
  border-radius: 0.65em;
  background: color-mix(in srgb, currentColor 3%, transparent);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, currentColor 7%, transparent);
}
.aia-agent-kanban-col span {
  display: inline-flex;
  align-items: center;
  gap: 0.45em;
  font-size: 0.7em;
  font-weight: 600;
  color: color-mix(in srgb, currentColor 65%, transparent);
}
.aia-agent-kanban-col i {
  width: 0.55em;
  height: 0.55em;
  border-radius: 50%;
  background: var(--c);
}
.aia-agent-kanban-col:nth-child(2) i { background: var(--wait); }
.aia-agent-kanban-col:nth-child(3) i { background: var(--ok); }
.aia-agent-kanban-col b {
  min-width: 1.6em;
  padding: 0.1em 0.4em;
  box-sizing: border-box;
  border-radius: 999em;
  background: color-mix(in srgb, currentColor 7%, transparent);
  color: color-mix(in srgb, currentColor 60%, transparent);
  font: 600 0.62em ui-monospace, "SF Mono", "JetBrains Mono", Menlo, Consolas, monospace;
  text-align: center;
  animation: aia-agent-kanban-fade var(--d) linear infinite;
}
.aia-agent-kanban-col b::before { content: counter(n); }
.aia-agent-kanban-n1 {
  --aia-agent-kanban-c1: calc(2 - var(--s2));
  counter-reset: n var(--aia-agent-kanban-c1);
}
.aia-agent-kanban-n2 {
  --aia-agent-kanban-c2: calc(1 - var(--s1) + var(--s2) - var(--s3) + var(--s4));
  counter-reset: n var(--aia-agent-kanban-c2);
}
.aia-agent-kanban-n3 {
  --aia-agent-kanban-c3: calc(var(--s1) + var(--s3));
  counter-reset: n var(--aia-agent-kanban-c3);
}
.aia-agent-kanban-cards {
  position: absolute;
  left: 0.6em;
  top: 2.5em;
  margin: 0;
  padding: 0;
  list-style: none;
  animation: aia-agent-kanban-fade var(--d) linear infinite;
}
.aia-agent-kanban-card {
  --col: 0;
  --row: 0;
  --m: 0;
  position: absolute;
  left: 0.3em;
  top: 0;
  display: grid;
  grid-template-columns: 0.9em 1fr;
  align-content: center;
  column-gap: 0.45em;
  box-sizing: border-box;
  width: calc(var(--w) - 0.6em);
  height: 2.5em;
  padding: 0 0.5em;
  border-radius: 0.5em;
  background: color-mix(in srgb, currentColor 4%, transparent);
  box-shadow:
    inset 0 0 0 1px color-mix(in srgb, currentColor 12%, transparent),
    0 calc(0.1em + var(--m) * 0.9em) calc(0.25em + var(--m) * 1.6em) calc(var(--m) * -0.5em) rgb(0 0 0 / calc(0.12 + var(--m) * 0.3));
  transform:
    translate(calc(var(--col) * (var(--w) + var(--gap))), calc(var(--row) * 2.75em))
    rotate(calc(var(--m) * 4deg))
    scale(calc(1 + var(--m) * 0.06));
}
.aia-agent-kanban-a {
  --col: calc(var(--s2) + var(--s3));
  --m: calc((min(var(--s2), 1 - var(--s2)) + min(var(--s3), 1 - var(--s3))) * 2);
  z-index: 3;
}
.aia-agent-kanban-b {
  --col: var(--s4);
  --row: calc(1 - var(--s2));
  --m: calc(min(var(--s4), 1 - var(--s4)) * 2);
  z-index: 2;
}
.aia-agent-kanban-c {
  --col: calc(1 + var(--s1));
  --row: var(--s3);
  --m: calc(min(var(--s1), 1 - var(--s1)) * 2);
}
.aia-agent-kanban-d {
  --e: clamp(0, (var(--s4) - 0.45) * 1.8, 1);
  opacity: var(--e);
  transform: translateY(calc((1 - var(--e)) * -0.6em)) scale(calc(0.94 + var(--e) * 0.06));
}
.aia-agent-kanban-st {
  grid-row: 1 / 3;
  display: grid;
  place-items: center;
  width: 0.9em;
  height: 0.9em;
}
.aia-agent-kanban-st > * { grid-area: 1 / 1; }
.aia-agent-kanban-spin {
  width: 0.8em;
  height: 0.8em;
  box-sizing: border-box;
  border-radius: 50%;
  border: 0.12em solid color-mix(in srgb, var(--c) 25%, transparent);
  border-top-color: var(--c);
  opacity: clamp(0, 1 - var(--col) * 2, 1);
  animation: aia-agent-kanban-spin 0.8s linear infinite;
}
.aia-agent-kanban-wait {
  width: 0.45em;
  height: 0.45em;
  border-radius: 50%;
  background: var(--wait);
  box-shadow: 0 0 0 0.16em color-mix(in srgb, #d97706 22%, transparent);
  opacity: min(clamp(0, (var(--col) - 0.5) * 2, 1), clamp(0, (1.5 - var(--col)) * 2, 1));
}
.aia-agent-kanban-ok {
  width: 0.95em;
  height: 0.95em;
  color: var(--ok);
  stroke-width: 3;
  opacity: clamp(0, (var(--col) - 1.5) * 2, 1);
}
.aia-agent-kanban-card b,
.aia-agent-kanban-card code {
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
  opacity: calc(1 - clamp(0, (var(--col) - 1.5) * 2, 1) * 0.35);
}
.aia-agent-kanban-card b {
  font-size: 0.7em;
  font-weight: 600;
  line-height: 1.35;
}
.aia-agent-kanban-card code {
  color: color-mix(in srgb, currentColor 50%, transparent);
  font: 0.58em ui-monospace, "SF Mono", "JetBrains Mono", Menlo, Consolas, monospace;
}
@keyframes aia-agent-kanban-clock {
  0%, 9% { --aia-agent-kanban-t: 0; }
  16%, 29% { --aia-agent-kanban-t: 1; }
  36%, 49% { --aia-agent-kanban-t: 2; }
  56%, 69% { --aia-agent-kanban-t: 3; }
  76%, 96% { --aia-agent-kanban-t: 4; }
  97%, 100% { --aia-agent-kanban-t: 0; }
}
@keyframes aia-agent-kanban-fade {
  0%, 92% { opacity: 1; }
  95%, 97.5% { opacity: 0; }
  100% { opacity: 1; }
}
@keyframes aia-agent-kanban-spin {
  to { transform: rotate(360deg); }
}
@media (prefers-reduced-motion: reduce) {
  .aia-agent-kanban,
  .aia-agent-kanban-cards,
  .aia-agent-kanban-col b {
    animation: none;
    --aia-agent-kanban-t: 2;
  }
  .aia-agent-kanban-spin { animation-duration: 2.4s; }
}

@media (prefers-reduced-motion: reduce) {
  .aia-agent-kanban, .aia-agent-kanban *, .aia-agent-kanban::before, .aia-agent-kanban::after, .aia-agent-kanban *::before, .aia-agent-kanban *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

Customizing this snippet

  • Color: set --aia-color on the element or a parent. Currently previewing #3b82f6.
  • Base size: set --aia-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 ai animations