← back to Animated Dot Loaderscompare with ground truth →
model output
Gemini 3 Flash Preview
Animated Dot Loaders
A 0.78T 0.26
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>Converging Dots Loader</title>
7 <style>
8 :root {
9 --bg-color-inner: #1a1625;
10 --bg-color-outer: #0a090f;
11 --dot-color: rgba(255, 255, 255, 0.85);
12 --dot-size: 10px;
13 --dot-spacing: 14px;
14 --animation-duration: 3s;
15 }
16
17 * {
18 margin: 0;
19 padding: 0;
20 box-sizing: border-box;
21 }
22
23 body {
24 height: 100vh;
25 display: flex;
26 justify-content: center;
27 align-items: center;
28 background: radial-gradient(circle, var(--bg-color-inner) 0%, var(--bg-color-outer) 100%);
29 overflow: hidden;
30 }
31
32 .loader {
33 position: relative;
34 display: flex;
35 align-items: center;
36 justify-content: center;
37 width: 150px;
38 height: 50px;
39 }
40
41 .dot {
42 width: var(--dot-size);
43 height: var(--dot-size);
44 background-color: var(--dot-color);
45 border-radius: 50%;
46 position: absolute;
47 animation: move var(--animation-duration) cubic-bezier(0.45, 0, 0.55, 1) infinite;
48 box-shadow: 0 0 1px rgba(255, 255, 255, 0.2);
49 }
50
51 /*
52 The dots converge at the center (0) and then move back to their original positions.
53 Positions based on a 5-dot spread: -2, -1, 0, 1, 2 units of spacing.
54 */
55
56 .dot:nth-child(1) {
57 animation-name: move-1;
58 }
59 .dot:nth-child(2) {
60 animation-name: move-2;
61 }
62 .dot:nth-child(3) {
63 animation-name: move-3; /* Middle dot stays mostly still or pulses */
64 }
65 .dot:nth-child(4) {
66 animation-name: move-4;
67 }
68 .dot:nth-child(5) {
69 animation-name: move-5;
70 }
71
72 @keyframes move-1 {
73 0%, 100% { transform: translateX(calc(var(--dot-spacing) * -2.2)); opacity: 0.4; scale: 0.8; }
74 50% { transform: translateX(0); opacity: 1; scale: 1.1; }
75 }
76
77 @keyframes move-2 {
78 0%, 100% { transform: translateX(calc(var(--dot-spacing) * -1.1)); opacity: 0.6; scale: 0.9; }
79 50% { transform: translateX(0); opacity: 1; scale: 1.1; }
80 }
81
82 @keyframes move-3 {
83 0%, 100% { transform: translateX(0); opacity: 0.8; scale: 1; }
84 50% { transform: translateX(0); opacity: 1; scale: 1.1; }
85 }
86
87 @keyframes move-4 {
88 0%, 100% { transform: translateX(calc(var(--dot-spacing) * 1.1)); opacity: 0.6; scale: 0.9; }
89 50% { transform: translateX(0); opacity: 1; scale: 1.1; }
90 }
91
92 @keyframes move-5 {
93 0%, 100% { transform: translateX(calc(var(--dot-spacing) * 2.2)); opacity: 0.4; scale: 0.8; }
94 50% { transform: translateX(0); opacity: 1; scale: 1.1; }
95 }
96 </style>
97</head>
98<body>
99 <div class="loader">
100 <div class="dot"></div>
101 <div class="dot"></div>
102 <div class="dot"></div>
103 <div class="dot"></div>
104 <div class="dot"></div>
105 </div>
106</body>
107</html>