← back to Sequenced SplitText Animationcompare with ground truth →
model output
Gemini 3 Flash Preview
Sequenced SplitText Animation
A 0.93T 0.31
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>CSS & JS Animation Recreation</title>
7 <style>
8 :root {
9 --bg-top: #dbeafe;
10 --bg-bottom: #fee2e2;
11 --text-color: #4a5568;
12 --font-size: 24px;
13 --letter-spacing: 0.15em;
14 }
15
16 * {
17 margin: 0;
18 padding: 0;
19 box-sizing: border-box;
20 }
21
22 body {
23 height: 100vh;
24 display: flex;
25 justify-content: center;
26 align-items: center;
27 background: linear-gradient(180deg, var(--bg-top), var(--bg-bottom));
28 font-family: 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
29 overflow: hidden;
30 }
31
32 #animation-container {
33 text-align: center;
34 width: 100%;
35 max-width: 800px;
36 }
37
38 .line {
39 min-height: 1.5em;
40 margin-bottom: 0.5em;
41 color: var(--text-color);
42 font-size: var(--font-size);
43 letter-spacing: var(--letter-spacing);
44 text-transform: none;
45 display: block;
46 }
47
48 /* Char wrapper styles */
49 .char {
50 display: inline-block;
51 opacity: 0;
52 filter: blur(10px);
53 transition: transform 1.2s cubic-bezier(0.22, 1, 0.36, 1),
54 opacity 0.8s ease-out,
55 filter 0.8s ease-out;
56 }
57
58 /* State: Appearing */
59 .char.in {
60 opacity: 1;
61 filter: blur(0);
62 transform: translate(0, 0) scale(1);
63 }
64
65 /* State: Exploding/Exiting */
66 .char.out {
67 opacity: 0;
68 filter: blur(20px);
69 /* Values set via JS for randomness */
70 transform: translate(var(--tx), var(--ty)) rotate(var(--tr)) scale(1.2);
71 }
72
73 @media (max-width: 600px) {
74 :root {
75 --font-size: 18px;
76 }
77 }
78 </style>
79</head>
80<body>
81
82 <div id="animation-container">
83 <div id="line1" class="line"></div>
84 <div id="line2" class="line"></div>
85 </div>
86
87 <script>
88 const content = [
89 {
90 line1: "Do you know CSS Animation?",
91 line2: "It's really awesome!"
92 },
93 {
94 line1: "But when combined with JS Animation,",
95 line2: "It will be stunning awesome!"
96 }
97 ];
98
99 const line1El = document.getElementById('line1');
100 const line2El = document.getElementById('line2');
101
102 function splitToSpans(element, text) {
103 element.innerHTML = '';
104 text.split('').forEach(char => {
105 const span = document.createElement('span');
106 span.textContent = char === ' ' ? '\u00A0' : char;
107 span.className = 'char';
108
109 // Random explosion vectors
110 const tx = (Math.random() - 0.5) * 400 + 'px';
111 const ty = (Math.random() - 0.7) * 300 + 'px'; // Tend to fly upwards
112 const tr = (Math.random() - 0.5) * 90 + 'deg';
113
114 span.style.setProperty('--tx', tx);
115 span.style.setProperty('--ty', ty);
116 span.style.setProperty('--tr', tr);
117
118 element.appendChild(span);
119 });
120 }
121
122 async function animateMessage(index) {
123 const data = content[index];
124 splitToSpans(line1El, data.line1);
125 splitToSpans(line2El, data.line2);
126
127 const chars1 = line1El.querySelectorAll('.char');
128 const chars2 = line2El.querySelectorAll('.char');
129
130 // Phase 1: Fade In
131 chars1.forEach((char, i) => {
132 setTimeout(() => char.classList.add('in'), i * 40);
133 });
134
135 // Second line starts slightly after first begins
136 setTimeout(() => {
137 chars2.forEach((char, i) => {
138 setTimeout(() => char.classList.add('in'), i * 40);
139 });
140 }, 600);
141
142 // Phase 2: Wait then Explode (Exit)
143 // Wait total of 3 seconds from start of message
144 return new Promise(resolve => {
145 setTimeout(() => {
146 [...chars1, ...chars2].forEach((char, i) => {
147 // Stagger the exit slightly for organic feel
148 setTimeout(() => {
149 char.classList.remove('in');
150 char.classList.add('out');
151 }, Math.random() * 200);
152 });
153
154 // Allow time for exit animation before resolving
155 setTimeout(resolve, 1500);
156 }, 3000);
157 });
158 }
159
160 async function run() {
161 // First Cycle
162 await animateMessage(0);
163
164 // Short gap between sentences
165 setTimeout(async () => {
166 // Second Cycle
167 await animateMessage(1);
168 }, 200);
169 }
170
171 // Start animation on load
172 window.addEventListener('DOMContentLoaded', run);
173 </script>
174</body>
175</html>