← back to Pure CSS animated check markcompare with ground truth →
model output
Gemini 3 Flash Preview
Pure CSS animated check mark
A 0.91T 0.38
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>Success Animation Recreation</title>
7 <style>
8 :root {
9 --bg-color: #a2d2d2;
10 --circle-color: rgba(0, 0, 0, 0.4);
11 --checkmark-color: #ffffff;
12 --bar-color: #bdbdbd;
13 --transition-timing: cubic-bezier(0.175, 0.885, 0.32, 1.275);
14 }
15
16 body, html {
17 margin: 0;
18 padding: 0;
19 width: 100%;
20 height: 100%;
21 display: flex;
22 justify-content: center;
23 align-items: center;
24 background-color: var(--bg-color);
25 overflow: hidden;
26 }
27
28 .container {
29 position: relative;
30 width: 300px;
31 height: 300px;
32 display: flex;
33 justify-content: center;
34 align-items: center;
35 }
36
37 /* The thin outer circle */
38 .outer-circle {
39 position: absolute;
40 width: 180px;
41 height: 180px;
42 border: 1px solid var(--circle-color);
43 border-radius: 50%;
44 box-sizing: border-box;
45 top: 20%;
46 }
47
48 /* The grey decorative bar */
49 .grey-bar {
50 position: absolute;
51 width: 160px;
52 height: 14px;
53 background-color: var(--bar-color);
54 border-radius: 10px;
55 top: 48%;
56 left: 23%;
57 transform: rotate(15deg);
58 animation: bar-settle 1.2s var(--transition-timing) forwards;
59 opacity: 0.8;
60 z-index: 1;
61 }
62
63 /* The checkmark SVG */
64 .checkmark-svg {
65 position: absolute;
66 width: 120px;
67 height: 120px;
68 top: 32%;
69 z-index: 2;
70 overflow: visible;
71 }
72
73 .checkmark-path {
74 fill: none;
75 stroke: var(--checkmark-color);
76 stroke-width: 18;
77 stroke-linecap: round;
78 stroke-linejoin: round;
79 stroke-dasharray: 200;
80 stroke-dashoffset: 200;
81 animation:
82 draw-check 0.6s ease-out 0.2s forwards,
83 pop-check 0.8s var(--transition-timing) 0.1s forwards;
84 transform-origin: center;
85 }
86
87 /* Animations */
88
89 @keyframes draw-check {
90 to {
91 stroke-dashoffset: 0;
92 }
93 }
94
95 @keyframes pop-check {
96 0% {
97 transform: scale(0.5);
98 opacity: 0;
99 }
100 50% {
101 transform: scale(1.3);
102 opacity: 1;
103 }
104 100% {
105 transform: scale(1);
106 opacity: 1;
107 }
108 }
109
110 @keyframes bar-settle {
111 0% {
112 transform: rotate(20deg) scaleX(0.8);
113 top: 45%;
114 }
115 100% {
116 transform: rotate(0deg) scaleX(1);
117 top: 48%;
118 }
119 }
120
121 /* Subtle scale on the whole circle group to match the "impact" feel */
122 .animation-wrapper {
123 display: flex;
124 justify-content: center;
125 align-items: center;
126 animation: container-pop 0.5s var(--transition-timing) forwards;
127 }
128
129 @keyframes container-pop {
130 0% { transform: scale(0.9); }
131 100% { transform: scale(1); }
132 }
133
134 </style>
135</head>
136<body>
137
138 <div class="animation-wrapper">
139 <div class="container">
140 <!-- Background thin circle -->
141 <div class="outer-circle"></div>
142
143 <!-- Background grey bar -->
144 <div class="grey-bar"></div>
145
146 <!-- Success checkmark -->
147 <svg class="checkmark-svg" viewBox="0 0 100 100">
148 <path class="checkmark-path" d="M 20 50 L 42 72 L 80 34" />
149 </svg>
150 </div>
151 </div>
152
153 <script>
154 // Optional: Re-run animation on click for easier observation
155 document.body.addEventListener('click', () => {
156 const wrapper = document.querySelector('.animation-wrapper');
157 const newWrapper = wrapper.cloneNode(true);
158 wrapper.parentNode.replaceChild(newWrapper, wrapper);
159 });
160 </script>
161</body>
162</html>