A wavy arc grows, shrinks and rotates, like the Material 3 Expressive indicator. The squiggle is one precomputed SVG path, and pathLength keeps the dash values in plain percentages.
Also known as: material 3 expressive loading indicator, squiggly spinner, wavy progress circle.
<svg class="ldr-wavy-ring" viewBox="0 0 48 48" role="status" aria-label="Loading"> <path pathLength="100" d="M42 24C42.5 24.9 43.4 25.9 43.3 26.8C43.2 27.6 42 28.4 41.3 29.1C40.6 29.8 39.4 30.1 39 30.9C38.7 31.6 39.2 32.7 39.1 33.7C39.1 34.7 39.3 36.1 38.7 36.8C38.2 37.4 36.8 37.4 35.8 37.6C34.8 37.8 33.6 37.4 32.9 37.9C32.2 38.3 32 39.6 31.5 40.4C30.9 41.2 30.3 42.5 29.5 42.7C28.7 43 27.5 42.2 26.6 41.8C25.6 41.4 24.9 40.5 24 40.5C23.1 40.5 22.4 41.4 21.4 41.8C20.5 42.2 19.3 43 18.5 42.7C17.7 42.5 17.1 41.2 16.5 40.4C16 39.6 15.8 38.3 15.1 37.9C14.4 37.4 13.2 37.8 12.2 37.6C11.2 37.4 9.8 37.4 9.3 36.8C8.7 36.1 8.9 34.7 8.9 33.7C8.8 32.7 9.3 31.6 9 30.9C8.6 30.1 7.4 29.8 6.7 29.1C6 28.4 4.8 27.6 4.7 26.8C4.6 25.9 5.5 24.9 6 24C6.5 23.1 7.5 22.5 7.7 21.7C7.8 20.8 7 19.9 6.7 18.9C6.5 18 5.9 16.7 6.3 15.9C6.6 15.1 8 14.7 8.9 14.3C9.7 13.8 11 13.8 11.5 13.2C12.1 12.5 11.9 11.3 12.2 10.4C12.5 9.5 12.7 8.1 13.5 7.6C14.2 7.1 15.5 7.5 16.5 7.6C17.5 7.7 18.5 8.4 19.4 8.2C20.2 7.9 20.7 6.8 21.4 6.2C22.2 5.6 23.1 4.5 24 4.5C24.9 4.5 25.8 5.6 26.6 6.2C27.3 6.8 27.8 7.9 28.6 8.2C29.5 8.4 30.5 7.7 31.5 7.6C32.5 7.5 33.8 7.1 34.5 7.6C35.3 8.1 35.5 9.5 35.8 10.4C36.1 11.3 35.9 12.5 36.5 13.2C37 13.8 38.3 13.8 39.1 14.3C40 14.7 41.4 15.1 41.7 15.9C42.1 16.7 41.5 18 41.3 18.9C41 19.9 40.2 20.8 40.3 21.7C40.5 22.5 41.5 23.1 42 24Z"></path> </svg>
.ldr-wavy-ring {
--s: var(--ldr-size, 48px);
--c: var(--ldr-color, #3b82f6);
width: var(--s);
height: var(--s);
animation: ldr-wavy-ring-rotate 2.8s linear infinite;
}
.ldr-wavy-ring path {
fill: none;
stroke: var(--c);
stroke-width: 3.5;
stroke-linecap: round;
stroke-linejoin: round;
animation: ldr-wavy-ring-dash 1.5s cubic-bezier(0.45, 0, 0.2, 1) infinite;
}
@keyframes ldr-wavy-ring-rotate {
to { transform: rotate(360deg); }
}
@keyframes ldr-wavy-ring-dash {
0% { stroke-dasharray: 4 96; stroke-dashoffset: 0; }
50% { stroke-dasharray: 62 38; stroke-dashoffset: -8; }
100% { stroke-dasharray: 4 96; stroke-dashoffset: -100; }
}
@media (prefers-reduced-motion: reduce) {
.ldr-wavy-ring, .ldr-wavy-ring *, .ldr-wavy-ring::before, .ldr-wavy-ring::after, .ldr-wavy-ring *::before, .ldr-wavy-ring *::after {
animation-duration: 3s;
}
}--ldr-color on the element or a parent.
Currently previewing #3b82f6.--ldr-size. Every dimension in the snippet is
derived from it. Currently previewing 64px.animation shorthand.
Delays on the children are relative, so they keep their rhythm.role="status" and an
aria-label so screen readers announce the wait. The reduced-motion rule
at the end slows the animation for users who asked for less motion.