Back to the library
Guest arrival ring (bold)
Variant: Bold
The heaviest reading: 5px rings that swing wider, a larger chip crossing more of the frame, and companion dots that rest closer to full opacity. Use it as a hero or empty-state loader where the arrival is the only thing on screen. The wider ring excursion is capped at 1.12 so the stroke never crosses the stage bounds at the narrowest phone width.
loaderpresenceambientboldstatus
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>Guest arrival ring — bold</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;
--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;
--t: calc(var(--cycle) / var(--speed));
--ease-out: cubic-bezier(0.23, 1, 0.32, 1);
--ease-in-out: cubic-bezier(0.77, 0, 0.175, 1);
/* File-specific — weight axis only. */
--_ring-w: 5px;
--_ring-open: 0.8;
--_ring-wide: 1.12;
--_chip-travel: 38%;
--_dot-size: 13px;
--_dot-dim: 0.3;
--_stage: min(300px, 82vw);
}
* { box-sizing: border-box; }
html, body { margin: 0; }
body {
min-height: 100vh;
display: grid;
place-items: center;
background: var(--ivory);
font-family: system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
color: var(--slate);
}
.card {
width: min(360px, 92vw);
padding: clamp(18px, 5vw, 26px);
border-radius: calc(18px * var(--round));
background: var(--paper);
border: 1px solid var(--oat);
display: grid;
justify-items: center;
gap: clamp(12px, 3.5vw, 18px);
}
.stage {
position: relative;
width: var(--_stage);
height: calc(var(--_stage) * 0.52);
display: grid;
place-items: center;
}
.ring {
position: absolute;
width: calc(var(--_stage) * 0.42);
height: calc(var(--_stage) * 0.42);
border-radius: 50%;
border: var(--_ring-w) solid var(--clay);
opacity: 0;
transform: scale(var(--_ring-open));
animation: ring-open var(--t) var(--ease-out) infinite;
}
.ring.echo {
border-color: var(--olive);
animation-delay: calc(140ms / var(--speed));
}
@keyframes ring-open {
0% { transform: scale(var(--_ring-open)); opacity: 0; }
14% { transform: scale(var(--_ring-open)); opacity: 1; }
46% { transform: scale(var(--_ring-wide)); opacity: 0.72; }
74% { transform: scale(var(--_ring-wide)); opacity: 0.62; }
92% { transform: scale(var(--_ring-open)); opacity: 0; }
100% { transform: scale(var(--_ring-open)); opacity: 0; }
}
.chip {
position: absolute;
width: calc(var(--_stage) * 0.25);
height: calc(var(--_stage) * 0.25);
border-radius: 50%;
background: var(--clay-d);
display: grid;
place-items: center;
opacity: 0;
/* the 90ms lead is fixed across the family; only distance grows here */
animation: chip-arrive var(--t) var(--ease-out) calc(90ms / var(--speed)) infinite;
}
.chip svg { width: 50%; height: 50%; display: block; }
.chip path { fill: none; stroke: var(--paper); stroke-width: 2.6; stroke-linecap: round; stroke-linejoin: round; }
@keyframes chip-arrive {
0% { transform: translateX(calc(-1 * var(--_chip-travel))) scale(0.9); opacity: 0; }
22% { transform: translateX(0) scale(1); opacity: 1; }
76% { transform: translateX(0) scale(1); opacity: 1; }
90% { transform: translateX(0) scale(0.92); opacity: 0; }
100% { transform: translateX(0) scale(0.92); opacity: 0; }
}
.seats {
position: absolute;
inset: 0;
display: grid;
place-items: center;
pointer-events: none;
}
.seat {
position: absolute;
width: var(--_dot-size);
height: var(--_dot-size);
border-radius: 50%;
background: var(--rust);
opacity: var(--_dot-dim);
transform: rotate(var(--_a)) translateX(calc(var(--_stage) * 0.3)) rotate(calc(-1 * var(--_a)));
animation: seat-fill var(--t) var(--ease-in-out) var(--_d) infinite;
}
.seat:nth-child(1) { --_a: -46deg; --_d: calc(360ms / var(--speed)); }
.seat:nth-child(2) { --_a: 0deg; --_d: calc(420ms / var(--speed)); }
.seat:nth-child(3) { --_a: 46deg; --_d: calc(480ms / var(--speed)); }
@keyframes seat-fill {
0% { opacity: var(--_dot-dim); }
16% { opacity: 1; }
70% { opacity: 1; }
88% { opacity: var(--_dot-dim); }
100% { opacity: var(--_dot-dim); }
}
.label {
font-size: clamp(11px, 3vw, 13px);
letter-spacing: 0.06em;
text-transform: uppercase;
color: var(--slate);
opacity: 0.72;
}
@media (max-width: 380px) {
.card { padding: 14px; gap: 10px; }
}
@media (prefers-reduced-motion: reduce) {
.ring {
transform: scale(1);
animation: ring-hold calc(var(--t) * 2.2) var(--ease-in-out) infinite;
}
.ring.echo { animation-delay: calc(300ms / var(--speed)); }
.chip {
transform: none;
animation: soft-hold calc(var(--t) * 2.2) var(--ease-in-out) calc(200ms / var(--speed)) infinite;
}
.seat {
transform: rotate(var(--_a)) translateX(calc(var(--_stage) * 0.3)) rotate(calc(-1 * var(--_a)));
animation: seat-fill calc(var(--t) * 2.2) var(--ease-in-out) var(--_d) infinite;
}
@keyframes ring-hold {
0%, 100% { opacity: 0.45; }
50% { opacity: 1; }
}
@keyframes soft-hold {
0%, 100% { opacity: 0.6; }
50% { opacity: 1; }
}
}
</style>
</head>
<body>
<div class="card">
<div class="stage">
<div class="ring"></div>
<div class="ring echo"></div>
<div class="seats">
<span class="seat"></span>
<span class="seat"></span>
<span class="seat"></span>
</div>
<div class="chip">
<svg viewBox="0 0 24 24" aria-hidden="true">
<path d="M12 4.5a3.4 3.4 0 1 1 0 6.8 3.4 3.4 0 0 1 0-6.8Z" />
<path d="M4.8 19.4c0-3.3 3.2-5.3 7.2-5.3s7.2 2 7.2 5.3" />
</svg>
</div>
</div>
<div class="label">Someone is joining</div>
</div>
</body>
</html>
The variant family
Same idea, one axis moved. Compare them side by side before you commit.