animation2code benchmark
For best compatibility, please view this dashboard in a Chrome browser.
← back to Sequenced SplitText Animation

model output

Gemini 3 Flash Preview

Sequenced SplitText Animation

A 0.93T 0.31
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>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>