A dark video generation panel: frames fill into a filmstrip left to right behind a scrubbing playhead, the preview shows the newest frame with its sun setting, and a frame counter climbs to 120.
Also known as: ai video generation animation, video rendering progress css, frame scrubber animation, text to video loading.
<div class="aia-video-timeline" role="status" aria-label="Generating video">
<div class="aia-video-timeline-top">
<span class="aia-video-timeline-preview aia-video-timeline-scene"></span>
<div class="aia-video-timeline-info">
<b>Generating video</b>
<span class="aia-video-timeline-frame"></span>
<span class="aia-video-timeline-spec">5 s · 24 fps · 1080p</span>
</div>
</div>
<div class="aia-video-timeline-strip" aria-hidden="true">
<i class="aia-video-timeline-scene" style="--k: 0.000; --s: 0.0"></i>
<i class="aia-video-timeline-scene" style="--k: 0.111; --s: 0.1"></i>
<i class="aia-video-timeline-scene" style="--k: 0.222; --s: 0.2"></i>
<i class="aia-video-timeline-scene" style="--k: 0.333; --s: 0.3"></i>
<i class="aia-video-timeline-scene" style="--k: 0.444; --s: 0.4"></i>
<i class="aia-video-timeline-scene" style="--k: 0.556; --s: 0.5"></i>
<i class="aia-video-timeline-scene" style="--k: 0.667; --s: 0.6"></i>
<i class="aia-video-timeline-scene" style="--k: 0.778; --s: 0.7"></i>
<i class="aia-video-timeline-scene" style="--k: 0.889; --s: 0.8"></i>
<i class="aia-video-timeline-scene" style="--k: 1.000; --s: 0.9"></i>
<span class="aia-video-timeline-head"></span>
</div>
</div>@property --aia-video-timeline-t {
syntax: "<number>";
inherits: true;
initial-value: 0;
}
@property --aia-video-timeline-n {
syntax: "<integer>";
inherits: false;
initial-value: 0;
}
.aia-video-timeline {
--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;
display: grid;
gap: 0.8em;
width: 24em;
padding: 0.9em;
box-sizing: border-box;
border-radius: 1em;
color: #f4f4f5;
background: linear-gradient(180deg, #17171d, #0d0d11);
box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.08), 0 1em 2em -1em rgba(0, 0, 0, 0.5);
animation: aia-video-timeline-clock 7s cubic-bezier(0.4, 0, 0.6, 1) infinite;
}
.aia-video-timeline-top {
display: flex;
gap: 0.9em;
align-items: center;
}
.aia-video-timeline-scene {
background:
linear-gradient(180deg, transparent 64%, #1d2a44 64%, #0e1626),
radial-gradient(circle at 58% calc(22% + var(--k) * 46%), #fff3d6 0 6%, transparent 6.6%),
radial-gradient(circle at 58% calc(22% + var(--k) * 46%), color-mix(in oklab, var(--c) 20%, #ffb35c), transparent 40%),
linear-gradient(180deg, color-mix(in oklab, var(--c) 70%, #0b0b2a), color-mix(in oklab, var(--c) 40%, #ff7a59) 50%, #ffc98f 64%);
}
.aia-video-timeline-preview {
--k: var(--aia-video-timeline-t);
flex: none;
width: 10.6em;
height: 6em;
border-radius: 0.5em;
box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.1);
}
.aia-video-timeline-info {
display: grid;
gap: 0.3em;
}
.aia-video-timeline-info b {
font-size: 0.95em;
font-weight: 600;
}
.aia-video-timeline-frame {
font-size: 0.8em;
font-variant-numeric: tabular-nums;
color: color-mix(in srgb, var(--c) 55%, #fff);
counter-reset: aia-video-timeline-n var(--aia-video-timeline-n);
animation: aia-video-timeline-count 7s cubic-bezier(0.4, 0, 0.6, 1) infinite;
}
.aia-video-timeline-frame::before { content: "Frame " counter(aia-video-timeline-n) " of 120"; }
.aia-video-timeline-spec {
font-size: 0.72em;
color: rgba(255, 255, 255, 0.5);
}
.aia-video-timeline-strip {
position: relative;
display: grid;
grid-template-columns: repeat(10, 1fr);
gap: 0.18em;
height: 1.6em;
}
.aia-video-timeline-strip i {
position: relative;
border-radius: 0.2em;
overflow: hidden;
}
.aia-video-timeline-strip i::after {
content: "";
position: absolute;
inset: 0;
background: repeating-linear-gradient(135deg, #24242c 0 0.25em, #1c1c22 0.25em 0.5em);
opacity: calc(1 - clamp(0, (var(--aia-video-timeline-t) - var(--s)) * 25, 1));
}
.aia-video-timeline-head {
position: absolute;
top: -0.3em;
bottom: -0.3em;
left: calc(var(--aia-video-timeline-t) * 100%);
width: 0.14em;
margin-left: -0.07em;
border-radius: 1em;
background: #fff;
box-shadow: 0 0 0.5em color-mix(in srgb, var(--c) 90%, transparent);
}
@keyframes aia-video-timeline-clock {
0% { --aia-video-timeline-t: 0; }
82%, 90% { --aia-video-timeline-t: 1; }
100% { --aia-video-timeline-t: 0; }
}
@keyframes aia-video-timeline-count {
0% { --aia-video-timeline-n: 0; }
82%, 90% { --aia-video-timeline-n: 120; }
100% { --aia-video-timeline-n: 0; }
}
@media (prefers-reduced-motion: reduce) {
.aia-video-timeline,
.aia-video-timeline-frame { animation: none; }
.aia-video-timeline { --aia-video-timeline-t: 0.72; }
.aia-video-timeline-frame { --aia-video-timeline-n: 86; }
}
@media (prefers-reduced-motion: reduce) {
.aia-video-timeline, .aia-video-timeline *, .aia-video-timeline::before, .aia-video-timeline::after, .aia-video-timeline *::before, .aia-video-timeline *::after {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
}
}--aia-color on the element or a parent.
Currently previewing #3b82f6.--aia-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.