Back to the library
Colonnade deploy, linear
Variant: Linear
The colonnade build with linear entrances. Every stone moves at a constant rate and stops dead, so the sequence reads as a metered progress readout more than a physical settle. Use it next to a determinate pipeline, such as a step counter or log stream, where the motion should feel mechanical and steady instead of expressive. Only the entrances go linear. The exits keep the shared ease-out fade, so dismantling still clears the stage quickly and doesn't drag.
deployloaderstaggerprogressarchitecture
The source
A complete HTML document. Paste it into an empty .html file and it plays — no stylesheet, script, font, or image to fetch.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Colonnade deploy, linear</title>
<style>
:root {
/* Neutrals — fixed, never remixed. */
--ivory: #faf9f5;
--paper: #ffffff;
--oat: #e3dacc;
--slate: #141413;
/* Knobs — the remix API. A knob exists iff declared here and used below. */
--hue: 38.8;
--lift: 0;
--chroma: 1;
--round: 1; /* include ONLY if at least one border-radius is wrapped below */
--speed: 1;
/* Accents — derived from the knobs with the family's offsets baked in,
so one hue roll moves them together. Defaults reproduce the original hex
(#d97757 / #b85c3e / #788c5d / #b04a3f). */
--clay: oklch(calc(0.6724 + var(--lift)) calc(0.1308 * var(--chroma)) var(--hue));
--clay-d: oklch(calc(0.5797 + var(--lift)) calc(0.127 * var(--chroma)) var(--hue));
--olive: oklch(calc(0.6118 + var(--lift)) calc(0.0713 * var(--chroma)) calc(var(--hue) + 88.3));
--rust: oklch(calc(0.5408 + var(--lift)) calc(0.1357 * var(--chroma)) calc(var(--hue) - 10.3));
/* Clock — every duration in the document runs off --t. */
--cycle: 3.6s; /* the authored master loop */
--t: calc(var(--cycle) / var(--speed));
--ease-out: cubic-bezier(0.23, 1, 0.32, 1); /* include only if used */
}
* { box-sizing: border-box; }
body {
margin: 0;
min-height: 100vh;
display: grid;
place-items: center;
background: var(--ivory);
color: var(--slate);
font-family: system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
}
.card {
display: grid;
justify-items: center;
gap: clamp(8px, 2.5vw, 14px);
padding: clamp(16px, 4vw, 24px) clamp(20px, 6vw, 36px);
background: var(--paper);
border: 1px solid var(--oat);
border-radius: calc(16px * var(--round));
}
.temple {
display: block;
width: min(220px, 60vw, 72vh);
height: auto;
overflow: visible;
}
.marble { fill: var(--ivory); stroke: var(--oat); stroke-width: 1.5; }
.flute { fill: none; stroke: var(--oat); stroke-width: 1; }
.stone { fill: var(--oat); }
.triglyph { fill: var(--olive); }
.pediment-face { fill: var(--clay); }
.tympanum { fill: none; stroke: var(--clay-d); stroke-width: 1.5; stroke-linejoin: round; }
.col, .beam, .pediment { transform-box: fill-box; }
/* 60ms per column: five columns finish inside ~750ms, before the beam lands. */
.col {
animation: rise var(--t) infinite both;
animation-delay: calc(var(--_i) * 0.06s / var(--speed));
}
.beam { --_i: 6; animation: cap-beam var(--t) infinite both; }
.pediment { --_i: 8; animation: cap-pediment var(--t) infinite both; }
.status {
display: grid;
font-size: clamp(11px, 3.2vw, 13px);
font-weight: 600;
letter-spacing: 0.2em;
text-transform: uppercase;
line-height: 1.3;
}
.status > span {
grid-area: 1 / 1;
display: inline-flex;
align-items: center;
justify-content: center;
gap: 0.6em;
}
.building { color: var(--clay-d); animation: say-building var(--t) infinite both; }
.deployed { color: var(--slate); animation: say-deployed var(--t) infinite both; }
.seal { width: 1.3em; height: 1.3em; flex: none; }
.seal circle { fill: var(--olive); }
.seal path { fill: none; stroke: var(--paper); stroke-width: 2.2; stroke-linecap: round; stroke-linejoin: round; }
@keyframes rise {
0%, 6% { opacity: 0; transform: translateY(104%); animation-timing-function: linear; }
14% { opacity: 1; transform: translateY(0); }
86% { opacity: 1; transform: translateY(0); animation-timing-function: var(--ease-out); }
91%, 100% { opacity: 0; transform: translateY(0); }
}
@keyframes cap-beam {
0%, 22% { opacity: 0; transform: translateY(-8px); animation-timing-function: linear; }
29% { opacity: 1; transform: translateY(0); }
85% { opacity: 1; transform: translateY(0); animation-timing-function: var(--ease-out); }
89%, 100% { opacity: 0; transform: translateY(0); }
}
@keyframes cap-pediment {
0%, 27% { opacity: 0; transform: translateY(-12px); animation-timing-function: linear; }
35% { opacity: 1; transform: translateY(0); }
84% { opacity: 1; transform: translateY(0); animation-timing-function: var(--ease-out); }
88%, 100% { opacity: 0; transform: translateY(0); }
}
@keyframes say-building {
0%, 36% { opacity: 1; animation-timing-function: var(--ease-out); }
40% { opacity: 0; }
88% { opacity: 0; animation-timing-function: var(--ease-out); }
93%, 100% { opacity: 1; }
}
@keyframes say-deployed {
0%, 39% { opacity: 0; transform: translateY(4px); animation-timing-function: linear; }
46% { opacity: 1; transform: translateY(0); }
84% { opacity: 1; transform: translateY(0); animation-timing-function: var(--ease-out); }
88%, 100% { opacity: 0; transform: translateY(0); }
}
@keyframes rest-rm {
0%, 6% { opacity: 0.3; animation-timing-function: linear; }
16% { opacity: 1; }
86% { opacity: 1; animation-timing-function: var(--ease-out); }
92%, 100% { opacity: 0.3; }
}
@keyframes say-deployed-rm {
0%, 39% { opacity: 0; animation-timing-function: linear; }
46% { opacity: 1; }
84% { opacity: 1; animation-timing-function: var(--ease-out); }
88%, 100% { opacity: 0; }
}
@media (max-width: 380px) {
.card { padding: 14px 18px; gap: 8px; }
.status { letter-spacing: 0.16em; }
}
/* Stone stays put; the build reads as stones brightening in sequence at half pace. */
@media (prefers-reduced-motion: reduce) {
.col, .beam, .pediment {
animation: rest-rm calc(var(--t) * 2) infinite both;
animation-delay: calc(var(--_i) * 0.08s / var(--speed));
}
.building { animation-duration: calc(var(--t) * 2); }
.deployed { animation: say-deployed-rm calc(var(--t) * 2) infinite both; }
}
</style>
</head>
<body>
<div class="card">
<svg class="temple" viewBox="0 0 200 120" aria-hidden="true">
<defs>
<clipPath id="ground"><rect x="0" y="-20" width="200" height="124" /></clipPath>
</defs>
<g class="pediment">
<polygon class="pediment-face" points="16,40 100,10 184,40" />
<polygon class="tympanum" points="42.6,36.5 100,16 157.4,36.5" />
</g>
<g class="beam">
<rect class="stone" x="20" y="40" width="160" height="10" />
<rect class="triglyph" x="38" y="42" width="4" height="6" />
<rect class="triglyph" x="68" y="42" width="4" height="6" />
<rect class="triglyph" x="98" y="42" width="4" height="6" />
<rect class="triglyph" x="128" y="42" width="4" height="6" />
<rect class="triglyph" x="158" y="42" width="4" height="6" />
</g>
<g clip-path="url(#ground)">
<g class="col" style="--_i: 0">
<rect class="marble" x="31" y="50" width="18" height="4" />
<rect class="marble" x="34" y="54" width="12" height="46" />
<rect class="marble" x="32" y="100" width="16" height="4" />
<path class="flute" d="M38 57V97M42 57V97" />
</g>
<g class="col" style="--_i: 1">
<rect class="marble" x="61" y="50" width="18" height="4" />
<rect class="marble" x="64" y="54" width="12" height="46" />
<rect class="marble" x="62" y="100" width="16" height="4" />
<path class="flute" d="M68 57V97M72 57V97" />
</g>
<g class="col" style="--_i: 2">
<rect class="marble" x="91" y="50" width="18" height="4" />
<rect class="marble" x="94" y="54" width="12" height="46" />
<rect class="marble" x="92" y="100" width="16" height="4" />
<path class="flute" d="M98 57V97M102 57V97" />
</g>
<g class="col" style="--_i: 3">
<rect class="marble" x="121" y="50" width="18" height="4" />
<rect class="marble" x="124" y="54" width="12" height="46" />
<rect class="marble" x="122" y="100" width="16" height="4" />
<path class="flute" d="M128 57V97M132 57V97" />
</g>
<g class="col" style="--_i: 4">
<rect class="marble" x="151" y="50" width="18" height="4" />
<rect class="marble" x="154" y="54" width="12" height="46" />
<rect class="marble" x="152" y="100" width="16" height="4" />
<path class="flute" d="M158 57V97M162 57V97" />
</g>
</g>
<rect class="stone" x="14" y="104" width="172" height="6" />
<rect class="stone" x="8" y="111" width="184" height="7" opacity="0.7" />
</svg>
<div class="status" role="status">
<span class="building">Building</span>
<span class="deployed">
<svg class="seal" viewBox="0 0 20 20" aria-hidden="true">
<circle cx="10" cy="10" r="10" />
<path d="M6 10.4l2.7 2.7L14.2 7.4" />
</svg>
Deployed
</span>
</div>
</div>
</body>
</html>
The variant family
Same idea, one axis moved. Compare them side by side before you commit.