animation2code benchmark
For best compatibility, please view this dashboard in a Chrome browser.
← back to [single element] CSS Double Helix

model output

GPT-5.4

[single element] CSS Double Helix

A 0.89T 0.32
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>Dot Wave</title>
7<style>
8  :root{
9    --w: 1024;
10    --h: 768;
11    --dots: 18;
12    --duration: 2.4s;
13    --dot: 13px;
14    --small: 9px;
15    --amp: 32px;
16    --gap: 40px;
17  }
18
19  html,body{
20    margin:0;
21    height:100%;
22    overflow:hidden;
23    background:#000;
24  }
25
26  body{
27    display:grid;
28    place-items:center;
29    font-family:sans-serif;
30  }
31
32  .scene{
33    position:relative;
34    width:100vw;
35    height:100vh;
36    overflow:hidden;
37    background:
38      radial-gradient(ellipse at 50% 50%, rgba(132,255,92,.95) 0%, rgba(170,220,150,.72) 22%, rgba(170,170,150,.38) 48%, rgba(150,150,170,.18) 72%, rgba(120,120,140,.08) 100%),
39      radial-gradient(circle at 0% 100%, rgba(30,90,255,.95) 0%, rgba(30,90,255,.55) 18%, rgba(30,90,255,0) 42%),
40      radial-gradient(circle at 100% 0%, rgba(255,90,30,.95) 0%, rgba(255,90,30,.55) 18%, rgba(255,90,30,0) 42%),
41      radial-gradient(circle at 0% 0%, rgba(120,70,200,.75) 0%, rgba(120,70,200,.35) 18%, rgba(120,70,200,0) 38%),
42      linear-gradient(135deg, #7f8ea0 0%, #a8b39a 45%, #b79f8f 100%);
43    filter: saturate(1.05) blur(0px);
44  }
45
46  .band{
47    position:absolute;
48    left:50%;
49    top:50%;
50    width:calc((var(--dots) - 1) * var(--gap) + 40px);
51    height:120px;
52    transform:translate(-50%,-50%);
53  }
54
55  .row{
56    position:absolute;
57    left:0;
58    width:100%;
59    height:40px;
60  }
61
62  .row.top{ top:22px; }
63  .row.bottom{ top:58px; }
64
65  .dot{
66    position:absolute;
67    left:calc(var(--i) * var(--gap));
68    top:50%;
69    width:var(--size);
70    height:var(--size);
71    margin-left:calc(var(--size) / -2);
72    margin-top:calc(var(--size) / -2);
73    border-radius:50%;
74    background:#fff;
75    transform:translateY(var(--y));
76    animation: wave var(--duration) linear infinite;
77    animation-delay:calc(var(--phase) * -1s);
78    will-change:transform;
79    box-shadow:0 0 0 0.2px rgba(255,255,255,.9);
80  }
81
82  @keyframes wave{
83    0%   { transform:translateY(calc(var(--base) + var(--dir) * -1 * var(--amp))); }
84    25%  { transform:translateY(calc(var(--base) + var(--dir) *  0 * var(--amp))); }
85    50%  { transform:translateY(calc(var(--base) + var(--dir) *  1 * var(--amp))); }
86    75%  { transform:translateY(calc(var(--base) + var(--dir) *  0 * var(--amp))); }
87    100% { transform:translateY(calc(var(--base) + var(--dir) * -1 * var(--amp))); }
88  }
89
90  /* soften overall look a bit like the source frames */
91  .scene::after{
92    content:"";
93    position:absolute;
94    inset:0;
95    background:rgba(255,255,255,.03);
96    pointer-events:none;
97  }
98</style>
99</head>
100<body>
101<div class="scene">
102  <div class="band">
103    <div class="row top" id="topRow"></div>
104    <div class="row bottom" id="bottomRow"></div>
105  </div>
106</div>
107
108<script>
109  const dots = 18;
110  const topRow = document.getElementById('topRow');
111  const bottomRow = document.getElementById('bottomRow');
112
113  // Alternating large/small dots with opposite phase between rows.
114  // Phase offset across x creates the traveling zig-zag seen in the frames.
115  for (let i = 0; i < dots; i++) {
116    const large = i % 2 === 0;
117    const phase = (i / 4.5); // horizontal travel cadence
118
119    const t = document.createElement('div');
120    t.className = 'dot';
121    t.style.setProperty('--i', i);
122    t.style.setProperty('--size', large ? '13px' : '9px');
123    t.style.setProperty('--base', '0px');
124    t.style.setProperty('--dir', large ? '-1' : '1');
125    t.style.setProperty('--amp', large ? '16px' : '8px');
126    t.style.setProperty('--phase', phase);
127    topRow.appendChild(t);
128
129    const b = document.createElement('div');
130    b.className = 'dot';
131    b.style.setProperty('--i', i);
132    b.style.setProperty('--size', large ? '13px' : '9px');
133    b.style.setProperty('--base', '0px');
134    b.style.setProperty('--dir', large ? '1' : '-1');
135    b.style.setProperty('--amp', large ? '16px' : '8px');
136    b.style.setProperty('--phase', phase + 0.6); // row offset to match interleaving motion
137    bottomRow.appendChild(b);
138  }
139</script>
140</body>
141</html>