A ring of small dots with a wave of larger, brighter dots traveling around it. The big dots sit under an SVG mask whose soft dash circles the outline, so dots swell in place instead of sliding.
Also known as: css dotted border animation, animated dotted border, dot ripple border.
<div class="bdr-dotted-wave-border">
<svg class="bdr-dotted-wave-border-svg" aria-hidden="true">
<defs>
<mask id="bdr-dotted-wave-border-mask"><rect class="bdr-dotted-wave-border-sweep" width="100%" height="100%" pathLength="100"/></mask>
</defs>
<rect class="bdr-dotted-wave-border-dots" width="100%" height="100%" pathLength="100"/>
<rect class="bdr-dotted-wave-border-big" width="100%" height="100%" pathLength="100" mask="url(#bdr-dotted-wave-border-mask)"/>
</svg>
Listening
</div>.bdr-dotted-wave-border {
--c: var(--bdr-color, #3b82f6);
font-size: var(--bdr-size, 16px);
position: relative;
display: grid;
place-items: center;
width: 15em;
height: 8.5em;
border-radius: 1em;
font-family: system-ui, sans-serif;
font-weight: 600;
background: color-mix(in srgb, var(--c) 5%, transparent);
}
.bdr-dotted-wave-border-svg {
position: absolute;
inset: 0;
width: 100%;
height: 100%;
overflow: visible;
pointer-events: none;
}
.bdr-dotted-wave-border-svg rect {
rx: 1em;
fill: none;
stroke-linecap: round;
}
.bdr-dotted-wave-border-dots {
stroke: color-mix(in srgb, var(--c) 55%, transparent);
stroke-width: 0.24em;
stroke-dasharray: 0 2.5;
}
.bdr-dotted-wave-border-big {
stroke: var(--c);
stroke-width: 0.5em;
stroke-dasharray: 0 2.5;
}
.bdr-dotted-wave-border-sweep {
stroke: #fff;
stroke-width: 1.2em;
stroke-dasharray: 24 76;
filter: blur(0.7em);
animation: bdr-dotted-wave-border-sweep 2.8s linear infinite;
}
@keyframes bdr-dotted-wave-border-sweep {
to { stroke-dashoffset: -100; }
}
@media (prefers-reduced-motion: reduce) {
.bdr-dotted-wave-border, .bdr-dotted-wave-border *, .bdr-dotted-wave-border::before, .bdr-dotted-wave-border::after, .bdr-dotted-wave-border *::before, .bdr-dotted-wave-border *::after {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
}
}--bdr-color on the element or a parent.
Currently previewing #3b82f6.--bdr-size. Every other dimension is in
em, so the whole thing scales together. Currently previewing 16px.transition or animation
shorthand. Staggered delays are relative, so they keep their rhythm.