← back to Animated Dot Loaderscompare with ground truth →
model output
GPT-5.4
Animated Dot Loaders
A 0.96T 0.17
1<!DOCTYPE html>
2<html lang="en">
3<head>
4<meta charset="UTF-8" />
5<meta name="viewport" content="width=device-width, initial-scale=1.0" />
6<title>Dot Loader Replica</title>
7<style>
8 :root{
9 --bg:#17141f;
10 --bg2:#24123a;
11 --dot:#a8a1ad;
12 --active:#f4f2f7;
13 --size:20px;
14 --gap:9px;
15 --lift:22px;
16 --dur:1.45s;
17 }
18
19 html,body{
20 height:100%;
21 margin:0;
22 }
23
24 body{
25 display:grid;
26 place-items:center;
27 overflow:hidden;
28 background:
29 radial-gradient(circle at 50% 50%,
30 rgba(58,24,96,.42) 0%,
31 rgba(42,20,70,.28) 18%,
32 rgba(28,18,46,.14) 34%,
33 rgba(23,20,31,0) 58%),
34 linear-gradient(#1a1722,#17141f);
35 font-family:system-ui,sans-serif;
36 }
37
38 .stage{
39 position:relative;
40 width:220px;
41 height:120px;
42 display:grid;
43 place-items:center;
44 }
45
46 .dots{
47 position:relative;
48 width:calc(var(--size) * 5 + var(--gap) * 4);
49 height:calc(var(--size) + var(--lift) + 8px);
50 }
51
52 .dot{
53 position:absolute;
54 top:50%;
55 width:var(--size);
56 height:var(--size);
57 margin-top:calc(var(--size) / -2);
58 border-radius:50%;
59 background:var(--dot);
60 box-shadow:0 0 0 1px rgba(255,255,255,.03) inset;
61 animation: hop var(--dur) cubic-bezier(.42,0,.2,1) infinite;
62 }
63
64 .dot:nth-child(1){ left:calc((var(--size) + var(--gap)) * 0); animation-delay:0s; }
65 .dot:nth-child(2){ left:calc((var(--size) + var(--gap)) * 1); animation-delay:calc(var(--dur) * .12); }
66 .dot:nth-child(3){ left:calc((var(--size) + var(--gap)) * 2); animation-delay:calc(var(--dur) * .24); }
67 .dot:nth-child(4){ left:calc((var(--size) + var(--gap)) * 3); animation-delay:calc(var(--dur) * .36); }
68 .dot:nth-child(5){ left:calc((var(--size) + var(--gap)) * 4); animation-delay:calc(var(--dur) * .48); }
69
70 @keyframes hop{
71 0%, 12%{
72 transform:translateY(0) scale(1);
73 background:var(--dot);
74 }
75 18%{
76 transform:translateY(-6px) scale(1);
77 background:color-mix(in srgb, var(--active) 70%, var(--dot));
78 }
79 30%{
80 transform:translateY(calc(var(--lift) * -1)) scale(1);
81 background:var(--active);
82 }
83 42%{
84 transform:translateY(-8px) scale(1);
85 background:color-mix(in srgb, var(--active) 72%, var(--dot));
86 }
87 54%, 100%{
88 transform:translateY(0) scale(1);
89 background:var(--dot);
90 }
91 }
92
93 /* fallback if color-mix isn't supported */
94 @supports not (background: color-mix(in srgb, white 50%, black)) {
95 @keyframes hop{
96 0%, 12%{
97 transform:translateY(0) scale(1);
98 background:var(--dot);
99 }
100 18%{
101 transform:translateY(-6px) scale(1);
102 background:#d8d3dd;
103 }
104 30%{
105 transform:translateY(calc(var(--lift) * -1)) scale(1);
106 background:var(--active);
107 }
108 42%{
109 transform:translateY(-8px) scale(1);
110 background:#d8d3dd;
111 }
112 54%, 100%{
113 transform:translateY(0) scale(1);
114 background:var(--dot);
115 }
116 }
117 }
118</style>
119</head>
120<body>
121 <div class="stage">
122 <div class="dots" aria-label="loading animation" role="img">
123 <span class="dot"></span>
124 <span class="dot"></span>
125 <span class="dot"></span>
126 <span class="dot"></span>
127 <span class="dot"></span>
128 </div>
129 </div>
130</body>
131</html>