← back to Only CSS: Text Slicercompare with ground truth →
model output
GPT-5.4
Only CSS: Text Slicer
A 0.63T 0.33
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>