animation2code benchmark
For best compatibility, please view this dashboard in a Chrome browser.
← back to Loaders (WIP)

model output

GPT-5.4

Loaders (WIP)

A 0.93T 0.21
compare with ground truth →
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>Three Dots Loader</title>
7<style>
8  :root{
9    --bg:#ef4b3a;
10    --dot:#f7f2ef;
11    --ghost:rgba(247,242,239,.38);
12    --size:12px;
13    --gap:13px;
14    --dur:1.8s;
15  }
16
17  html,body{
18    margin:0;
19    width:100%;
20    height:100%;
21    overflow:hidden;
22    background:var(--bg);
23  }
24
25  body{
26    position:relative;
27    font-family:sans-serif;
28  }
29
30  .loader{
31    position:absolute;
32    left:50%;
33    top:8.2%;
34    width:calc(var(--size) * 3 + var(--gap) * 2);
35    height:var(--size);
36    transform:translateX(-50%);
37  }
38
39  .dot{
40    position:absolute;
41    top:0;
42    width:var(--size);
43    height:var(--size);
44    border-radius:50%;
45    background:var(--dot);
46    animation:dotCycle var(--dur) cubic-bezier(.45,0,.55,1) infinite;
47    will-change:transform, opacity;
48  }
49
50  .dot::after{
51    content:"";
52    position:absolute;
53    inset:0;
54    border-radius:50%;
55    background:var(--ghost);
56    transform:translateX(0) scale(1);
57    opacity:0;
58    animation:trailCycle var(--dur) cubic-bezier(.45,0,.55,1) infinite;
59    will-change:transform, opacity;
60  }
61
62  .d1{ left:0; animation-delay:0s; }
63  .d2{ left:calc(var(--size) + var(--gap)); animation-delay:0s; }
64  .d3{ left:calc((var(--size) + var(--gap)) * 2); animation-delay:0s; }
65
66  .d1::after{ animation-delay:0s; }
67  .d2::after{ animation-delay:0s; }
68  .d3::after{ animation-delay:0s; }
69
70  @keyframes dotCycle{
71    0%, 18%   { transform:translateX(0); opacity:1; }
72    32%       { transform:translateX(calc(var(--size) + var(--gap))); opacity:1; }
73    50%       { transform:translateX(calc(var(--size) + var(--gap))); opacity:1; }
74    64%       { transform:translateX(0); opacity:1; }
75    100%      { transform:translateX(0); opacity:1; }
76  }
77
78  /* phase offsets create the collapse to center dot, hold, then expand */
79  .d1{ animation-name:leftDot; }
80  .d2{ animation-name:centerDot; }
81  .d3{ animation-name:rightDot; }
82
83  @keyframes leftDot{
84    0%,20%    { transform:translateX(0); }
85    36%,64%   { transform:translateX(calc(var(--size) + var(--gap))); }
86    80%,100%  { transform:translateX(0); }
87  }
88
89  @keyframes centerDot{
90    0%,100%   { transform:translateX(0); }
91  }
92
93  @keyframes rightDot{
94    0%,20%    { transform:translateX(0); }
95    36%,64%   { transform:translateX(calc(-1 * (var(--size) + var(--gap)))); }
96    80%,100%  { transform:translateX(0); }
97  }
98
99  /* faint side remnants visible during merge/split */
100  .d1::after{ animation-name:leftTrail; }
101  .d2::after{ animation-name:centerTrail; }
102  .d3::after{ animation-name:rightTrail; }
103
104  @keyframes leftTrail{
105    0%,22%,78%,100% { opacity:0; transform:translateX(0) scale(1); }
106    30%             { opacity:1; transform:translateX(6px) scale(1.05); }
107    40%,60%         { opacity:.95; transform:translateX(10px) scale(1.05); }
108    70%             { opacity:1; transform:translateX(6px) scale(1.05); }
109  }
110
111  @keyframes centerTrail{
112    0%,100%         { opacity:0; transform:translateX(0) scale(1); }
113    34%             { opacity:.35; transform:translateX(-2px) scale(1.08); }
114    50%             { opacity:.18; transform:translateX(0) scale(1.12); }
115    66%             { opacity:.35; transform:translateX(2px) scale(1.08); }
116  }
117
118  @keyframes rightTrail{
119    0%,22%,78%,100% { opacity:0; transform:translateX(0) scale(1); }
120    30%             { opacity:1; transform:translateX(-6px) scale(1.05); }
121    40%,60%         { opacity:.95; transform:translateX(-10px) scale(1.05); }
122    70%             { opacity:1; transform:translateX(-6px) scale(1.05); }
123  }
124</style>
125</head>
126<body>
127  <div class="loader" aria-label="loading">
128    <span class="dot d1"></span>
129    <span class="dot d2"></span>
130    <span class="dot d3"></span>
131  </div>
132</body>
133</html>