Snippets / UI Components /

Success state

CSS-only success indicators with animated checkmarks, oklch() colors, and accessible focus states.

Form submitted

Your changes have been saved

Task completed

Great job! All items checked off

Upload complete

All files processed successfully

Widely supported
uino-js

Quick implementation

/* HTML: <div class="success-item" role="status">
           <div class="success-icon"></div>
           <div class="success-content">
             <h4>Success title</h4>
             <p>Success message</p>
           </div>
         </div> */

.success-icon {
  width: 1.5rem;
  height: 1.5rem;
  border-radius: 50%;
  background: oklch(0.72 0.14 155);
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}

/* Animated checkmark using ::after */
.success-icon::after {
  content: "";
  width: 0.35rem;
  height: 0.7rem;
  border: 2px solid white;
  border-top: none;
  border-left: none;
  transform: rotate(45deg) translate(0, 0);
  opacity: 0;
  animation: checkmark 0.25s ease-out forwards;
  animation-delay: 0.1s;
}

@keyframes checkmark {
  to {
    transform: rotate(45deg) translate(0, 0);
    opacity: 1;
  }
}

/* Accessible focus state */
.success-item:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* Respect reduced motion preference */
@media (prefers-reduced-motion: reduce) {
  .success-icon::after {
    animation: none;
    opacity: 1;
  }
}

Prompt this to your LLM

Crafted prompt — includes role, intent, constraints, framework variant, and edge cases.

You are a senior frontend engineer specializing in accessible UI components.

Goal: Create a success state indicator with an animated checkmark — no JavaScript for the animation.

Technical constraints:
- Use CSS animation on a ::after pseudo-element to draw the checkmark stroke.
- Use oklch() for all colors (success green: oklch(0.72 0.14 155), white border).
- The checkmark should animate in with opacity and transform on load or when the parent becomes visible.
- Include a focus-visible state for keyboard accessibility on interactive success items.
- Respects @media (prefers-reduced-motion: reduce) by disabling the animation.

Framework variant (pick one):
A) Vanilla HTML/CSS only — return a .success-item wrapper with .success-icon and .success-content classes.
B) React component — accept `title`, `message`, `onClose` props; return the structure with proper ARIA roles.

Edge cases to handle:
- Screen reader announcement: use role="status" and aria-live="polite" on the container for dynamic success messages.
- What if the animation is too fast for some users? Provide a reduced-motion fallback.
- Color contrast: ensure the white checkmark on the green background passes WCAG AA.

Return the HTML structure and CSS, clearly separated.

Why this matters in 2026

Success states are everywhere — form submissions, task completions, file uploads. The old pattern was to reach for JavaScript animations or SVG libraries for checkmarks. Now, a simple CSS pseudo-element with animation and oklch() colors delivers the same polish without the overhead. It's also easier to theme: swap the green value and the entire design system updates.

Plus, it's keyboard accessible out of the box. Add tabindex="0" and focus-visible styles, and you're WCAG compliant.

The logic

The checkmark: A ::after pseudo-element draws a 2-pixel border on the right and bottom edges, rotated 45 degrees to form the L-shape. Starting with opacity: 0 and a slight translate offset, the animation brings it to opacity: 1 for that "strokes in" effect.

oklch() for success green: oklch(0.72 0.14 155) is a perceptually uniform green that looks consistent across light and dark modes. No need for separate --success-color tokens per theme.

Reduced motion: The @media (prefers-reduced-motion: reduce) query disables the animation and shows the checkmark immediately — essential for users who experience motion sickness.

Accessibility & performance

For dynamic success messages (e.g., after form submission), use role="status" and aria-live="polite" so screen readers announce the update. Interactive items (like clickable success toasts) need tabindex="0" and visible focus rings.

Performance-wise, the animation only touches opacity and transform — both GPU-accelerated properties that don't trigger layout recalculations. On low-end devices, the reduced-motion fallback ensures instant rendering without animation overhead.

Pro tip: For inline success states next to form fields, pair the checkmark icon with a green border on the input itself for redundancy.