Stage Transition
CSSA vertical list of three circular markers changes states as an active deployment spinner moves down through test, build, and deploy phases.
- Tier
- CSS
- Dependencies
- None
- Duration
- 4 s, loops
- Categories
- Icons and micro-interactions, Data and progress
- Use cases
- Loading and waiting, Workflow and approvals
- Industries
- SaaS and software, Cross-industry
- Style
- Technical · light stroke
- Set
- deploy
- Tags
- loopprogresslineui
Companion assets
The same artwork, not animated. Derived from the entry’s own resting state, so it matches exactly.
Code
animation.svg
<svg xmlns="http://www.w3.org/2000/svg" aria-labelledby="deploy-stage-title" class="pulsar pulsar-deploy-stage" data-pulsar="deploy-stage" role="img" viewBox="0 0 160 96"><title id="deploy-stage-title">Vertical deployment stage transitions tracking multi-phase pipeline progression</title><g fill="none" stroke="currentColor" stroke-linecap="square" stroke-width=".75" opacity=".3"><path id="deploy-stage-datum" d="M20 20h8m-8 0v8m120-8h-8m8 0v8M20 76h8m-8 0v-8m120 8h-8m8 0v-8"></path><line id="deploy-stage-axis" x1="24" x2="136" y1="48" y2="48" stroke-dasharray="2 4"></line></g><line id="deploy-stage-spine" x1="48" x2="48" y1="30" y2="66" fill="none" stroke="currentColor" stroke-width="1.25" opacity=".3"></line><g id="deploy-stage-row-1"><circle cx="48" cy="30" r="5" fill="none" stroke="currentColor" stroke-width="1.2"></circle><path id="deploy-stage-check-1" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.25" d="m46 30 1.5 1.5 3-3" opacity="0"></path><line id="deploy-stage-bar-1" x1="58" x2="112" y1="30" y2="30" stroke="currentColor" stroke-width="1.5" opacity=".4"></line></g><g id="deploy-stage-row-2"><circle cx="48" cy="48" r="5" fill="none" stroke="currentColor" stroke-width="1.2"></circle><path id="deploy-stage-check-2" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.25" d="m46 48 1.5 1.5 3-3" opacity="0"></path><line id="deploy-stage-bar-2" x1="58" x2="120" y1="48" y2="48" stroke="currentColor" stroke-width="1.5" opacity=".4"></line></g><g id="deploy-stage-row-3"><circle cx="48" cy="66" r="5" fill="none" stroke="currentColor" stroke-width="1.2"></circle><path id="deploy-stage-check-3" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.25" d="m46 66 1.5 1.5 3-3" opacity="0"></path><line id="deploy-stage-bar-3" x1="58" x2="106" y1="66" y2="66" stroke="currentColor" stroke-width="1.5" opacity=".4"></line></g><circle id="deploy-stage-spinner" cx="48" cy="30" r="7" fill="none" stroke="currentColor" stroke-dasharray="6 8" stroke-width="1.25"></circle></svg>
animation.css
.pulsar-deploy-stage {
--pulsar-accent: currentColor;
}
.pulsar-deploy-stage #deploy-stage-spinner,
.pulsar-deploy-stage #deploy-stage-check-1,
.pulsar-deploy-stage #deploy-stage-check-2,
.pulsar-deploy-stage #deploy-stage-check-3 {
stroke: var(--pulsar-accent, currentColor);
}
.pulsar-deploy-stage #deploy-stage-spinner {
animation: deploy-stage-spin-move 4000ms cubic-bezier(0.4, 0, 0.2, 1) infinite;
transform-origin: 48px 30px;
}
.pulsar-deploy-stage #deploy-stage-check-1 {
animation: deploy-stage-c1 4000ms cubic-bezier(0.16, 1, 0.3, 1) infinite;
}
.pulsar-deploy-stage #deploy-stage-check-2 {
animation: deploy-stage-c2 4000ms cubic-bezier(0.16, 1, 0.3, 1) infinite;
}
.pulsar-deploy-stage #deploy-stage-check-3 {
animation: deploy-stage-c3 4000ms cubic-bezier(0.16, 1, 0.3, 1) infinite;
}
.pulsar-deploy-stage #deploy-stage-bar-1 {
animation: deploy-stage-b1 4000ms cubic-bezier(0.16, 1, 0.3, 1) infinite;
}
.pulsar-deploy-stage #deploy-stage-bar-2 {
animation: deploy-stage-b2 4000ms cubic-bezier(0.16, 1, 0.3, 1) infinite;
}
.pulsar-deploy-stage #deploy-stage-bar-3 {
animation: deploy-stage-b3 4000ms cubic-bezier(0.16, 1, 0.3, 1) infinite;
}
@keyframes deploy-stage-spin-move {
0% {
transform: translateY(0) rotate(0deg);
opacity: 1;
}
24% {
transform: translateY(0) rotate(180deg);
}
30% {
transform: translateY(18px) rotate(220deg);
}
54% {
transform: translateY(18px) rotate(400deg);
}
60% {
transform: translateY(36px) rotate(440deg);
}
84% {
transform: translateY(36px) rotate(620deg);
opacity: 1;
}
92% {
transform: translateY(36px) rotate(720deg);
opacity: 0;
}
96%,
100% {
transform: translateY(0) rotate(720deg);
opacity: 0;
}
}
@keyframes deploy-stage-c1 {
0%,
18% {
opacity: 0;
transform: scale(0.6);
}
24%,
90% {
opacity: 1;
transform: scale(1);
}
96%,
100% {
opacity: 0;
}
}
@keyframes deploy-stage-c2 {
0%,
48% {
opacity: 0;
transform: scale(0.6);
}
54%,
90% {
opacity: 1;
transform: scale(1);
}
96%,
100% {
opacity: 0;
}
}
@keyframes deploy-stage-c3 {
0%,
78% {
opacity: 0;
transform: scale(0.6);
}
84%,
90% {
opacity: 1;
transform: scale(1);
}
96%,
100% {
opacity: 0;
}
}
@keyframes deploy-stage-b1 {
0%,
18% {
stroke: currentColor;
opacity: 0.4;
}
24%,
90% {
stroke: var(--pulsar-accent, currentColor);
opacity: 0.85;
}
96%,
100% {
stroke: currentColor;
opacity: 0.4;
}
}
@keyframes deploy-stage-b2 {
0%,
48% {
stroke: currentColor;
opacity: 0.4;
}
54%,
90% {
stroke: var(--pulsar-accent, currentColor);
opacity: 0.85;
}
96%,
100% {
stroke: currentColor;
opacity: 0.4;
}
}
@keyframes deploy-stage-b3 {
0%,
78% {
stroke: currentColor;
opacity: 0.4;
}
84%,
90% {
stroke: var(--pulsar-accent, currentColor);
opacity: 0.85;
}
96%,
100% {
stroke: currentColor;
opacity: 0.4;
}
}
@media (prefers-reduced-motion: reduce) {
.pulsar-deploy-stage * {
animation: none !important;
transform: none;
}
.pulsar-deploy-stage #deploy-stage-check-1,
.pulsar-deploy-stage #deploy-stage-check-2,
.pulsar-deploy-stage #deploy-stage-check-3 {
opacity: 1;
}
}