AI CSS Animations

Four Image Batch Generating

Four images generating side by side: each tile shimmers with its own progress bar and resolves at its own pace while a counter reports how many are ready. One @property clock, four start times.

Also known as: ai image grid loading, image generation progress animation css, batch image generation ui, midjourney grid loading.

Generating 4 images Ceramic vase on linen, soft north light

HTML

<div class="aia-image-batch" role="status" aria-label="Generating 4 images">
  <div class="aia-image-batch-copy">
    <b>Generating 4 images</b>
    <span class="aia-image-batch-prompt">Ceramic vase on linen, soft north light</span>
    <span class="aia-image-batch-count"></span>
  </div>
  <div class="aia-image-batch-grid">
    <span class="aia-image-batch-tile" style="--s: 0.3; --v: var(--c); --w: #efe7dc"><i class="aia-image-batch-img"></i><i class="aia-image-batch-bar"></i></span>
    <span class="aia-image-batch-tile" style="--s: 0.44; --v: #c4704b; --w: #e9e1d6"><i class="aia-image-batch-img"></i><i class="aia-image-batch-bar"></i></span>
    <span class="aia-image-batch-tile" style="--s: 0.58; --v: #2f5d62; --w: #e6e3db"><i class="aia-image-batch-img"></i><i class="aia-image-batch-bar"></i></span>
    <span class="aia-image-batch-tile" style="--s: 0.7; --v: #d9c7a5; --w: #3b3a40"><i class="aia-image-batch-img"></i><i class="aia-image-batch-bar"></i></span>
  </div>
</div>

CSS

@property --aia-image-batch-t {
  syntax: "<number>";
  inherits: true;
  initial-value: 0;
}
@property --aia-image-batch-n {
  syntax: "<integer>";
  inherits: false;
  initial-value: 0;
}
.aia-image-batch {
  --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;
  --out: clamp(0, (0.96 - var(--aia-image-batch-t)) * 16, 1);
  display: flex;
  align-items: center;
  gap: 1.2em;
  animation: aia-image-batch-clock 6.5s linear infinite;
}
.aia-image-batch-copy {
  display: grid;
  gap: 0.35em;
  width: 10em;
}
.aia-image-batch-copy b {
  font-size: 0.95em;
  font-weight: 600;
  letter-spacing: -0.01em;
}
.aia-image-batch-prompt {
  font-size: 0.8em;
  line-height: 1.35;
  color: color-mix(in srgb, currentColor 60%, transparent);
}
.aia-image-batch-count {
  --aia-image-batch-n: calc(
    clamp(0, (var(--aia-image-batch-t) - 0.3) * 1000, 1) + clamp(0, (var(--aia-image-batch-t) - 0.44) * 1000, 1) +
    clamp(0, (var(--aia-image-batch-t) - 0.58) * 1000, 1) + clamp(0, (var(--aia-image-batch-t) - 0.7) * 1000, 1)
  );
  margin-top: 0.3em;
  font-size: 0.78em;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  color: var(--c);
  counter-reset: aia-image-batch-n var(--aia-image-batch-n);
}
.aia-image-batch-count::before { content: counter(aia-image-batch-n) " of 4 ready"; }
.aia-image-batch-grid {
  display: grid;
  grid-template-columns: repeat(2, 5.4em);
  gap: 0.35em;
}
.aia-image-batch-tile {
  --in: calc(clamp(0, (var(--aia-image-batch-t) - var(--s)) * 10, 1) * var(--out));
  position: relative;
  height: 5.4em;
  border-radius: 0.55em;
  overflow: hidden;
  background: linear-gradient(100deg, color-mix(in srgb, currentColor 7%, transparent) 30%, color-mix(in srgb, currentColor 15%, transparent) 50%, color-mix(in srgb, currentColor 7%, transparent) 70%) 0 0 / 300% 100%;
  animation: aia-image-batch-shimmer 1.6s linear infinite;
}
.aia-image-batch-img {
  position: absolute;
  inset: 0;
  background:
    radial-gradient(ellipse 9% 5% at 44% 28%, rgba(255, 255, 255, 0.7), transparent 70%),
    radial-gradient(ellipse 8% 3% at 50% 22%, color-mix(in srgb, var(--v) 70%, #000) 0 90%, transparent 100%),
    radial-gradient(ellipse 22% 30% at 50% 52%, var(--v) 0 97%, transparent 100%),
    linear-gradient(90deg, transparent 45.5%, var(--v) 45.5% 54.5%, transparent 54.5%) 0 22% / 100% 22% no-repeat,
    radial-gradient(ellipse 30% 6% at 50% 78%, rgba(0, 0, 0, 0.22), transparent 70%),
    linear-gradient(180deg, var(--w) 72%, color-mix(in srgb, var(--w) 82%, #000) 72%);
  opacity: var(--in);
  filter: blur(calc((1 - var(--in)) * 0.6em));
  scale: calc(1.08 - var(--in) * 0.08);
}
.aia-image-batch-bar {
  position: absolute;
  left: 0.45em;
  right: 0.45em;
  bottom: 0.45em;
  height: 0.2em;
  border-radius: 1em;
  background:
    linear-gradient(var(--c), var(--c)) 0 0 / calc(min(var(--aia-image-batch-t) / var(--s), 1) * 100%) 100% no-repeat,
    color-mix(in srgb, currentColor 15%, transparent);
  opacity: calc(1 - clamp(0, (var(--aia-image-batch-t) - var(--s)) * 10, 1));
}
@keyframes aia-image-batch-clock {
  to { --aia-image-batch-t: 1; }
}
@keyframes aia-image-batch-shimmer {
  from { background-position: 100% 0; }
  to { background-position: -50% 0; }
}
@media (prefers-reduced-motion: reduce) {
  .aia-image-batch { animation: none; --aia-image-batch-t: 0.62; }
  .aia-image-batch-tile { animation: none; }
}

@media (prefers-reduced-motion: reduce) {
  .aia-image-batch, .aia-image-batch *, .aia-image-batch::before, .aia-image-batch::after, .aia-image-batch *::before, .aia-image-batch *::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