Home / Snippets / Animation & Motion /
Pulse
Scale pulse and ring pulse — two variants for live indicators.
Quick implementation
/* Variant 1: Scale pulse */
@keyframes pulse {
0%, 100% { transform: scale(1); }
50% { transform: scale(1.15); }
}
.pulse {
animation: pulse 1.5s ease-in-out infinite;
}
/* Variant 2: Ring pulse (expanding border) */
.pulse-ring {
position: relative;
}
.pulse-ring::after {
content: '';
position: absolute;
inset: 0;
border-radius: 50%;
border: 2px solid oklch(0.72 0.19 265);
animation: pulse-ring 1.5s ease-out infinite;
}
@keyframes pulse-ring {
0% { transform: scale(1); opacity: 1; }
100% { transform: scale(2); opacity: 0; }
}
@media (prefers-reduced-motion: reduce) {
.pulse, .pulse-ring::after { animation: none; }
}
Prompt this to your LLM
Includes role, constraints, two framework variants, and edge cases to handle.
You are a senior frontend engineer building a CSS animation library.
Goal: Two pulse animation variants — a scale pulse and a ring (expanding border) pulse. No JavaScript.
Technical constraints:
- Scale pulse: transform: scale() only — no layout shift.
- Ring pulse: ::after pseudo-element that scales up and fades out.
- Use oklch() for all colors, not hex or rgba().
- Both animations should be infinite and smooth (ease-in-out / ease-out).
- Include @media (prefers-reduced-motion: reduce) to disable both.
Framework variant (pick one):
A) Vanilla CSS classes applicable to any element.
B) React component — accept variant ("scale" | "ring"), color, and size props.
Edge cases to handle:
- Pulse should not cause layout shift for surrounding elements.
- Ring pulse needs position: relative on the parent element.
- Both variants should work on circles and rectangles.
Return CSS.
Why this matters in 2026
Pulse animations signal "live" or "active" state — think notification dots, recording indicators, and online status badges. Two CSS classes replace what many teams build with JavaScript animation libraries.
The logic
The scale pulse uses transform: scale(1.15) at the midpoint, creating a breathing effect. The ring pulse uses a ::after pseudo-element that scales up while fading out, creating an expanding ring. Both use transform and opacity — the two cheapest properties to animate on the GPU compositor.
Accessibility & performance
Infinite animations can be distracting for users with vestibular disorders. @media (prefers-reduced-motion: reduce) stops both variants entirely. For non-critical indicators, consider using a subtle pulse that only runs a few times rather than infinitely. Both animations use compositor-only properties for 60fps rendering.