← back to Sequenced SplitText Animationcompare with ground truth →
model output
Claude Sonnet 4.6
Sequenced SplitText Animation
A 0.80T 0.22
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</title>
7<style>
8 * { margin: 0; padding: 0; box-sizing: border-box; }
9
10 body {
11 width: 100vw;
12 height: 100vh;
13 background: linear-gradient(to bottom, #dce8f5 0%, #f0eef5 50%, #ede8ec 100%);
14 display: flex;
15 align-items: center;
16 justify-content: center;
17 font-family: 'Helvetica Neue', Arial, sans-serif;
18 overflow: hidden;
19 }
20
21 #stage {
22 text-align: center;
23 position: relative;
24 }
25
26 .text-line {
27 font-size: 1.5rem;
28 font-weight: 300;
29 letter-spacing: 0.25em;
30 color: #3d5a6a;
31 line-height: 1.8;
32 white-space: nowrap;
33 overflow: hidden;
34 }
35
36 .char {
37 display: inline-block;
38 opacity: 1;
39 transition: none;
40 }
41
42 .char.faded {
43 opacity: 0.3;
44 color: #8aabb8;
45 }
46</style>
47</head>
48<body>
49<div id="stage">
50 <div class="text-line" id="line1"></div>
51 <div class="text-line" id="line2"></div>
52</div>
53
54<script>
55 const scenes = [
56 {
57 line1: "Do you know CSS Animation?",
58 line2: "It's really awesome!",
59 duration: 6000
60 },
61 {
62 line1: "But when combined with JS Animation,",
63 line2: "It will be stunning awesome!",
64 duration: 6000
65 }
66 ];
67
68 let currentScene = 0;
69
70 function animateText(el, text, delay, onComplete) {
71 el.innerHTML = '';
72 const chars = text.split('');
73 chars.forEach((ch, i) => {
74 const span = document.createElement('span');
75 span.className = 'char';
76 span.textContent = ch === ' ' ? '\u00A0' : ch;
77 span.style.opacity = '0';
78 span.style.color = '#8aabb8';
79 el.appendChild(span);
80 });
81
82 const spans = el.querySelectorAll('.char');
83 let i = 0;
84 const interval = 60;
85
86 function revealNext() {
87 if (i < spans.length) {
88 // Fade in current char
89 spans[i].style.transition = 'opacity 0.3s ease, color 0.5s ease';
90 spans[i].style.opacity = '1';
91 // After a bit, solidify color
92 const idx = i;
93 setTimeout(() => {
94 spans[idx].style.color = '#3d5a6a';
95 }, 300);
96 i++;
97 setTimeout(revealNext, interval);
98 } else {
99 if (onComplete) setTimeout(onComplete, 500);
100 }
101 }
102
103 setTimeout(revealNext, delay);
104 }
105
106 function exitText(el, onComplete) {
107 const spans = el.querySelectorAll('.char');
108 // Zoom out + blur effect: scale down and fade
109 el.style.transition = 'transform 0.8s ease-in, opacity 0.8s ease-in, filter 0.8s ease-in';
110 el.style.transform = 'scale(0.3) translateY(-30px)';
111 el.style.opacity = '0';
112 el.style.filter = 'blur(8px)';
113 setTimeout(() => {
114 el.style.transition = 'none';
115 el.style.transform = '';
116 el.style.opacity = '';
117 el.style.filter = '';
118 el.innerHTML = '';
119 if (onComplete) onComplete();
120 }, 900);
121 }
122
123 function runScene(sceneIndex) {
124 const scene = scenes[sceneIndex];
125 const line1 = document.getElementById('line1');
126 const line2 = document.getElementById('line2');
127
128 // Reset
129 line1.style.transition = 'none';
130 line2.style.transition = 'none';
131 line1.style.transform = '';
132 line2.style.transform = '';
133 line1.style.opacity = '';
134 line2.style.opacity = '';
135 line1.style.filter = '';
136 line2.style.filter = '';
137
138 animateText(line1, scene.line1, 0, () => {
139 animateText(line2, scene.line2, 0, () => {
140 // Hold for a bit then exit
141 setTimeout(() => {
142 exitText(line1, () => {});
143 exitText(line2, () => {
144 // Next scene
145 currentScene = (currentScene + 1) % scenes.length;
146 setTimeout(() => runScene(currentScene), 300);
147 });
148 }, 2500);
149 });
150 });
151 }
152
153 // Start
154 runScene(0);
155</script>
156</body>
157</html>