animation2code benchmark
For best compatibility, please view this dashboard in a Chrome browser.
← back to Only CSS: Text Slicer

model output

GPT-5.4

Only CSS: Text Slicer

A 0.63T 0.33
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" />
6<title>Happy Halloween Animation</title>
7<style>
8  :root{
9    --bg:#1a0004;
10    --w:1024;
11    --h:768;
12  }
13  html,body{
14    margin:0;
15    width:100%;
16    height:100%;
17    overflow:hidden;
18    background:var(--bg);
19    font-family: Impact, Haettenschweiler, "Arial Black", sans-serif;
20  }
21  .stage{
22    position:relative;
23    width:100vw;
24    height:100vh;
25    background:var(--bg);
26    overflow:hidden;
27  }
28  .center{
29    position:absolute;
30    left:50%;
31    top:50%;
32    width:min(78vw, 800px);
33    height:min(52vw, 530px);
34    transform:translate(-50%,-50%);
35  }
36
37  .word{
38    position:absolute;
39    left:50%;
40    transform:translateX(-50%);
41    display:flex;
42    gap:.02em;
43    white-space:nowrap;
44    z-index:2;
45  }
46  .word.top{ top:18%; font-size:clamp(72px, 10vw, 118px); }
47  .word.bottom{ top:43%; font-size:clamp(72px, 10vw, 118px); }
48
49  .letter{
50    position:relative;
51    display:inline-block;
52    width:.72em;
53    height:1em;
54    overflow:visible;
55  }
56  .glyph{
57    position:absolute;
58    inset:0;
59    display:flex;
60    align-items:center;
61    justify-content:center;
62    font-weight:900;
63    line-height:1;
64    color:transparent;
65    background:
66      linear-gradient(90deg,
67        #5fd0c8 0 14%,
68        #f0c34a 14% 28%,
69        #b56cff 28% 42%,
70        #ff5db8 42% 56%,
71        #5f6cff 56% 70%,
72        #b8ff3f 70% 84%,
73        #f4f4ea 84% 100%);
74    background-size:220% 100%;
75    background-position:calc(var(--hueShift,0) * 1%) 0;
76    -webkit-background-clip:text;
77    background-clip:text;
78    text-shadow:none;
79    opacity:0;
80    animation: settleOpacity 4.8s linear forwards;
81    animation-delay: var(--delay);
82  }
83
84  .piece{
85    position:absolute;
86    inset:0;
87    display:flex;
88    align-items:center;
89    justify-content:center;
90    font-weight:900;
91    line-height:1;
92    color:transparent;
93    background:
94      linear-gradient(90deg,
95        #5fd0c8 0 14%,
96        #f0c34a 14% 28%,
97        #b56cff 28% 42%,
98        #ff5db8 42% 56%,
99        #5f6cff 56% 70%,
100        #b8ff3f 70% 84%,
101        #f4f4ea 84% 100%);
102    background-size:220% 100%;
103    background-position:calc(var(--hueShift,0) * 1%) 0;
104    -webkit-background-clip:text;
105    background-clip:text;
106    clip-path: polygon(var(--clip));
107    opacity:.98;
108    transform-origin:50% 50%;
109    animation: fly var(--dur,4.8s) cubic-bezier(.18,.72,.18,1) forwards;
110    animation-delay: var(--delay);
111    filter: brightness(.98);
112  }
113
114  .smile{
115    position:absolute;
116    left:14%;
117    top:72%;
118    width:90px;
119    height:120px;
120    z-index:2;
121  }
122  .smile .piece,
123  .smile .glyph{
124    font-size:clamp(92px, 11vw, 132px);
125  }
126
127  @keyframes fly{
128    0%{
129      opacity:0;
130      transform:
131        translate(calc(var(--sx) * 1vw), calc(var(--sy) * 1vh))
132        rotate(calc(var(--sr) * 1deg))
133        scale(.55);
134    }
135    8%{ opacity:.12; }
136    22%{ opacity:.45; }
137    55%{
138      opacity:1;
139      transform:
140        translate(calc(var(--mx,0) * 1vw), calc(var(--my,0) * 1vh))
141        rotate(calc(var(--mr,0) * 1deg))
142        scale(1.06);
143    }
144    78%{
145      opacity:1;
146      transform:
147        translate(calc(var(--ox,0) * 1px), calc(var(--oy,0) * 1px))
148        rotate(calc(var(--or,0) * 1deg))
149        scale(.985);
150    }
151    100%{
152      opacity:1;
153      transform:
154        translate(0px,0px)
155        rotate(0deg)
156        scale(1);
157    }
158  }
159
160  @keyframes settleOpacity{
161    0%,78%{ opacity:0; }
162    100%{ opacity:1; }
163  }
164
165  .dust{
166    position:absolute;
167    inset:0;
168    pointer-events:none;
169    z-index:1;
170  }
171  .dust i{
172    position:absolute;
173    width:2px;
174    height:42px;
175    background:linear-gradient(to bottom, transparent, rgba(255,255,255,.45), transparent);
176    opacity:0;
177    transform:rotate(var(--a));
178    animation: streak 2.2s linear forwards;
179    animation-delay:var(--d);
180    mix-blend-mode:screen;
181  }
182  @keyframes streak{
183    0%{opacity:0; transform:translate(0,0) rotate(var(--a)) scaleY(.2);}
184    20%{opacity:.35;}
185    100%{opacity:0; transform:translate(var(--tx),var(--ty)) rotate(var(--a)) scaleY(1.2);}
186  }
187</style>
188</head>
189<body>
190<div class="stage">
191  <div class="center" id="scene">
192    <div class="word top" id="topWord"></div>
193    <div class="word bottom" id="bottomWord"></div>
194    <div class="smile" id="smile"></div>
195    <div class="dust" id="dust"></div>
196  </div>
197</div>
198
199<script>
200const paletteShift = [0,18,36,54,72,90,108,126,144,162,180,198];
201const clips = [
202  "0 0, 100% 0, 100% 34%, 0 26%",
203  "0 24%, 100% 34%, 100% 66%, 0 56%",
204  "0 58%, 100% 68%, 100% 100%, 0 100%",
205  "0 0, 54% 0, 42% 100%, 0 100%",
206  "48% 0, 100% 0, 100% 100%, 58% 100%"
207];
208
209function mulberry32(a){return function(){let t=a+=0x6D2B79F5;t=Math.imul(t^t>>>15,t|1);t^=t+Math.imul(t^t>>>7,t|61);return((t^t>>>14)>>>0)/4294967296}}
210const rand = mulberry32(666);
211
212function r(min,max){ return min + (max-min)*rand(); }
213function ri(min,max){ return Math.floor(r(min,max+1)); }
214
215function makeLetter(ch, idx, total, row){
216  const el = document.createElement('span');
217  el.className = 'letter';
218  const baseDelay = row === 0 ? 1.15 : 1.55;
219  const delay = baseDelay + idx * 0.11 + r(-0.03,0.03);
220
221  const glyph = document.createElement('span');
222  glyph.className = 'glyph';
223  glyph.textContent = ch;
224  glyph.style.setProperty('--delay', `${delay}s`);
225  glyph.style.setProperty('--hueShift', paletteShift[idx % paletteShift.length]);
226  el.appendChild(glyph);
227
228  const pieceCount = 4;
229  for(let i=0;i<pieceCount;i++){
230    const p = document.createElement('span');
231    p.className = 'piece';
232    p.textContent = ch;
233    p.style.setProperty('--clip', clips[(i + idx) % clips.length]);
234    p.style.setProperty('--delay', `${delay + i*0.015}s`);
235    p.style.setProperty('--dur', `${4.6 + r(-.15,.2)}s`);
236    p.style.setProperty('--hueShift', paletteShift[(idx*2+i) % paletteShift.length]);
237
238    const side = idx < total/2 ? -1 : 1;
239    const sx = r(18,48) * side + r(-8,8);
240    const sy = r(-34,34);
241    const sr = r(-160,160);
242    const mx = sx * .28;
243    const my = sy * .22;
244    const mr = sr * .18;
245    const ox = r(-18,18);
246    const oy = r(-14,14);
247    const or = r(-12,12);
248
249    p.style.setProperty('--sx', sx.toFixed(2));
250    p.style.setProperty('--sy', sy.toFixed(2));
251    p.style.setProperty('--sr', sr.toFixed(2));
252    p.style.setProperty('--mx', mx.toFixed(2));
253    p.style.setProperty('--my', my.toFixed(2));
254    p.style.setProperty('--mr', mr.toFixed(2));
255    p.style.setProperty('--ox', ox.toFixed(2));
256    p.style.setProperty('--oy', oy.toFixed(2));
257    p.style.setProperty('--or', or.toFixed(2));
258    el.appendChild(p);
259  }
260  return el;
261}
262
263function buildWord(target, text, row){
264  [...text].forEach((ch, idx) => {
265    target.appendChild(makeLetter(ch, idx, text.length, row));
266  });
267}
268
269buildWord(document.getElementById('topWord'), 'HAPPY', 0);
270buildWord(document.getElementById('bottomWord'), 'HALLOWEEN', 1);
271
272// smiley made from colon + parenthesis, stacked like the reference
273const smile = document.getElementById('smile');
274[':',')'].forEach((ch, idx)=>{
275  const wrap = document.createElement('div');
276  wrap.className = 'letter';
277  wrap.style.position = 'absolute';
278  wrap.style.left = '0';
279  wrap.style.top = idx === 0 ? '0' : '34px';
280  wrap.style.width = '1em';
281  wrap.style.height = '1em';
282
283  const glyph = document.createElement('span');
284  glyph.className = 'glyph';
285  glyph.textContent = ch;
286  glyph.style.setProperty('--delay', `${2.15 + idx*0.08}s`);
287  glyph.style.setProperty('--hueShift', `${40 + idx*30}`);
288  wrap.appendChild(glyph);
289
290  for(let i=0;i<4;i++){
291    const p = document.createElement('span');
292    p.className = 'piece';
293    p.textContent = ch;
294    p.style.setProperty('--clip', clips[(i+idx)%clips.length]);
295    p.style.setProperty('--delay', `${2.15 + idx*0.08 + i*0.02}s`);
296    p.style.setProperty('--dur', `4.4s`);
297    p.style.setProperty('--hueShift', `${40 + idx*30 + i*12}`);
298    p.style.setProperty('--sx', `${r(-8,10)}`);
299    p.style.setProperty('--sy', `${r(-8,12)}`);
300    p.style.setProperty('--sr', `${r(-80,80)}`);
301    p.style.setProperty('--mx', `${r(-4,4)}`);
302    p.style.setProperty('--my', `${r(-4,4)}`);
303    p.style.setProperty('--mr', `${r(-10,10)}`);
304    p.style.setProperty('--ox', `${r(-6,6)}`);
305    p.style.setProperty('--oy', `${r(-6,6)}`);
306    p.style.setProperty('--or', `${r(-6,6)}`);
307    wrap.appendChild(p);
308  }
309  smile.appendChild(wrap);
310});
311
312// ambient flying shards / streaks to mimic the scattered fragments in early frames
313const dust = document.getElementById('dust');
314for(let i=0;i<26;i++){
315  const s = document.createElement('i');
316  s.style.left = `${r(4,96)}%`;
317  s.style.top = `${r(8,92)}%`;
318  s.style.setProperty('--a', `${r(-55,55)}deg`);
319  s.style.setProperty('--d', `${0.9 + r(0.2,1.8)}s`);
320  s.style.setProperty('--tx', `${r(-120,120)}px`);
321  s.style.setProperty('--ty', `${r(-80,80)}px`);
322  dust.appendChild(s);
323}
324</script>
325</body>
326</html>