A gradient ring pops out around a social icon and keeps spinning while you hover, like a story ring. The ring is a masked conic gradient on a pseudo-element; the icon shrinks to leave a gap.
Also known as: spinning gradient border icon, story ring hover css, rotating ring social icons.
<ul class="hfx-icon-gradient-ring"> <li><a class="hfx-icon-gradient-ring-link" href="#" aria-label="Photos"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M14.5 4h-5L7 7H4a2 2 0 0 0-2 2v9a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2V9a2 2 0 0 0-2-2h-3Z"/><circle cx="12" cy="13" r="3.5"/></svg></a></li> <li><a class="hfx-icon-gradient-ring-link" href="#" aria-label="Like"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M19 14c1.5-1.5 3-3.2 3-5.5A5.5 5.5 0 0 0 16.5 3c-1.8 0-3 .5-4.5 2-1.5-1.5-2.7-2-4.5-2A5.5 5.5 0 0 0 2 8.5c0 2.3 1.5 4 3 5.5l7 7Z"/></svg></a></li> <li><a class="hfx-icon-gradient-ring-link" href="#" aria-label="Chat"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M21 11.5a8.4 8.4 0 0 1-12.2 7.5L3 21l2-5.3A8.5 8.5 0 1 1 21 11.5Z"/></svg></a></li> </ul>
.hfx-icon-gradient-ring {
--c: var(--hfx-color, #3b82f6);
font-size: var(--hfx-size, 16px);
display: flex;
align-items: center;
gap: 1.1em;
margin: 0;
padding: 0;
list-style: none;
}
.hfx-icon-gradient-ring-link {
position: relative;
display: grid;
place-items: center;
width: 3.25em;
height: 3.25em;
border-radius: 50%;
color: var(--c);
}
.hfx-icon-gradient-ring-link::after {
content: "";
position: absolute;
inset: 0;
border-radius: 50%;
background: color-mix(in srgb, var(--c) 12%, transparent);
transition: scale 0.4s cubic-bezier(0.34, 1.56, 0.64, 1), background-color 0.3s ease;
}
.hfx-icon-gradient-ring-link::before {
content: "";
position: absolute;
inset: -0.3em;
border-radius: 50%;
background: conic-gradient(var(--c), color-mix(in srgb, var(--c) 30%, #fff) 25%, var(--c) 50%, color-mix(in srgb, var(--c) 15%, transparent) 75%, var(--c));
-webkit-mask: radial-gradient(farthest-side, transparent calc(100% - 0.22em), #000 calc(100% - 0.2em));
mask: radial-gradient(farthest-side, transparent calc(100% - 0.22em), #000 calc(100% - 0.2em));
opacity: 0;
scale: 0.75;
transition: opacity 0.25s ease, scale 0.45s cubic-bezier(0.34, 1.56, 0.64, 1);
}
.hfx-icon-gradient-ring-link svg {
position: relative;
z-index: 1;
width: 1.4em;
height: 1.4em;
transition: scale 0.4s cubic-bezier(0.34, 1.56, 0.64, 1);
}
.hfx-icon-gradient-ring-link:is(:hover, :focus-visible)::before {
opacity: 1;
scale: 1;
animation: hfx-icon-gradient-ring-spin 1.6s linear infinite;
}
.hfx-icon-gradient-ring-link:is(:hover, :focus-visible)::after {
scale: 0.86;
background: color-mix(in srgb, var(--c) 20%, transparent);
}
.hfx-icon-gradient-ring-link:is(:hover, :focus-visible) svg { scale: 0.92; }
@keyframes hfx-icon-gradient-ring-spin {
to { rotate: 1turn; }
}
@media (prefers-reduced-motion: reduce) {
.hfx-icon-gradient-ring, .hfx-icon-gradient-ring *, .hfx-icon-gradient-ring::before, .hfx-icon-gradient-ring::after, .hfx-icon-gradient-ring *::before, .hfx-icon-gradient-ring *::after {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
}
}--hfx-color on the element or a parent.
Currently previewing #3b82f6.--hfx-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.