← back to Only CSS: Star Warp Displaycompare with ground truth →
model output
Claude Sonnet 4.6
Only CSS: Star Warp Display
A 0.66T 0.27
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>Star Warp Animation</title>
7<style>
8 * { margin: 0; padding: 0; box-sizing: border-box; }
9
10 body {
11 background: #0d1f35;
12 display: flex;
13 justify-content: center;
14 align-items: center;
15 min-height: 100vh;
16 overflow: hidden;
17 }
18
19 .phone {
20 width: 290px;
21 height: 490px;
22 background: #000;
23 border-radius: 8px;
24 border: 2px solid #1a1a2e;
25 position: relative;
26 overflow: hidden;
27 box-shadow:
28 0 20px 60px rgba(0,0,0,0.8),
29 0 0 0 1px rgba(255,255,255,0.05),
30 inset 0 1px 0 rgba(255,255,255,0.1);
31 }
32
33 .phone::before {
34 content: '';
35 position: absolute;
36 top: 0;
37 left: 0;
38 right: 0;
39 bottom: 0;
40 background: linear-gradient(135deg, rgba(255,255,255,0.08) 0%, transparent 50%);
41 pointer-events: none;
42 z-index: 10;
43 border-radius: 6px;
44 }
45
46 .phone-shadow {
47 position: absolute;
48 bottom: -20px;
49 left: 10px;
50 right: 10px;
51 height: 30px;
52 background: rgba(0,0,0,0.4);
53 filter: blur(15px);
54 border-radius: 50%;
55 }
56
57 canvas {
58 position: absolute;
59 top: 0;
60 left: 0;
61 width: 100%;
62 height: 100%;
63 }
64</style>
65</head>
66<body>
67 <div style="position:relative;">
68 <div class="phone">
69 <canvas id="c"></canvas>
70 </div>
71 <div class="phone-shadow"></div>
72 </div>
73
74<script>
75const canvas = document.getElementById('c');
76const ctx = canvas.getContext('2d');
77
78canvas.width = 290;
79canvas.height = 490;
80
81const W = canvas.width;
82const H = canvas.height;
83const cx = W * 0.48;
84const cy = H * 0.42;
85
86class Star {
87 constructor() {
88 this.reset(true);
89 }
90
91 reset(initial) {
92 const angle = Math.random() * Math.PI * 2;
93 const dist = initial ? Math.random() * 80 + 5 : Math.random() * 10 + 2;
94
95 this.x = cx + Math.cos(angle) * dist;
96 this.y = cy + Math.sin(angle) * dist;
97 this.angle = angle;
98 this.speed = Math.random() * 3 + 1.5;
99 this.length = Math.random() * 18 + 4;
100 this.opacity = Math.random() * 0.8 + 0.2;
101 this.width = Math.random() * 1.5 + 0.5;
102 this.dist = dist;
103 this.maxDist = Math.sqrt(W*W + H*H);
104
105 // Some stars are brighter/longer
106 if (Math.random() < 0.15) {
107 this.length = Math.random() * 60 + 30;
108 this.width = Math.random() * 2 + 1;
109 this.opacity = 1;
110 this.speed = Math.random() * 2 + 1;
111 }
112 }
113
114 update() {
115 this.dist += this.speed * (this.dist / 30 + 0.5);
116 this.x = cx + Math.cos(this.angle) * this.dist;
117 this.y = cy + Math.sin(this.angle) * this.dist;
118
119 if (this.x < -50 || this.x > W + 50 || this.y < -50 || this.y > H + 50) {
120 this.reset(false);
121 }
122 }
123
124 draw() {
125 const tailX = this.x - Math.cos(this.angle) * this.length * (this.dist / 80);
126 const tailY = this.y - Math.sin(this.angle) * this.length * (this.dist / 80);
127
128 const alpha = Math.min(1, this.opacity * (this.dist / 40));
129
130 const grad = ctx.createLinearGradient(tailX, tailY, this.x, this.y);
131 grad.addColorStop(0, `rgba(255,255,255,0)`);
132 grad.addColorStop(1, `rgba(255,255,255,${alpha})`);
133
134 ctx.beginPath();
135 ctx.moveTo(tailX, tailY);
136 ctx.lineTo(this.x, this.y);
137 ctx.strokeStyle = grad;
138 ctx.lineWidth = this.width;
139 ctx.lineCap = 'round';
140 ctx.stroke();
141 }
142}
143
144const stars = [];
145for (let i = 0; i < 80; i++) {
146 stars.push(new Star());
147}
148
149function animate() {
150 ctx.fillStyle = 'rgba(0,0,0,0.2)';
151 ctx.fillRect(0, 0, W, H);
152
153 for (const star of stars) {
154 star.update();
155 star.draw();
156 }
157
158 requestAnimationFrame(animate);
159}
160
161// Initial clear
162ctx.fillStyle = '#000';
163ctx.fillRect(0, 0, W, H);
164
165animate();
166</script>
167</body>
168</html>