Hashtags in mixed sizes that each pop, tilt their own way and fill with the accent when hovered. Every tag carries its size and tilt as two custom properties in its style attribute.
Also known as: hashtag hover css, tag cloud animation, keyword tags hover.
<ul class="hfx-tag-cloud"> <li><a href="#" style="--s: 1.3; --r: -5deg">css</a></li> <li><a href="#" style="--s: 0.95; --r: 4deg">animation</a></li> <li><a href="#" style="--s: 1.15; --r: -3deg">design</a></li> <li><a href="#" style="--s: 0.9; --r: 6deg">svg</a></li> <li><a href="#" style="--s: 1.2; --r: 3deg">motion</a></li> <li><a href="#" style="--s: 1; --r: -6deg">ui</a></li> <li><a href="#" style="--s: 1.05; --r: 5deg">tailwind</a></li> <li><a href="#" style="--s: 0.9; --r: -4deg">a11y</a></li> <li><a href="#" style="--s: 1.1; --r: 2deg">frontend</a></li> </ul>
.hfx-tag-cloud {
--c: var(--hfx-color, #3b82f6);
font-size: var(--hfx-size, 16px);
display: flex;
flex-wrap: wrap;
align-items: center;
justify-content: center;
gap: 0.35em 0.4em;
max-width: 19em;
margin: 0;
padding: 0;
list-style: none;
font-family: system-ui, sans-serif;
}
.hfx-tag-cloud a {
display: inline-block;
padding: 0.2em 0.55em;
border-radius: 99em;
color: color-mix(in srgb, currentColor 78%, transparent);
font-size: calc(var(--s, 1) * 1em);
font-weight: 600;
line-height: 1.3;
text-decoration: none;
transition: color 0.2s ease, background-color 0.2s ease, box-shadow 0.25s ease, transform 0.35s cubic-bezier(0.34, 1.56, 0.64, 1);
}
.hfx-tag-cloud a::before {
content: "#";
margin-right: 0.05em;
color: var(--c);
transition: color 0.2s ease;
}
.hfx-tag-cloud a:is(:hover, :focus-visible) {
background: var(--c);
box-shadow: 0 0.35em 0.8em -0.3em color-mix(in srgb, var(--c) 70%, transparent);
color: #fff;
transform: rotate(var(--r)) scale(1.15);
}
.hfx-tag-cloud a:is(:hover, :focus-visible)::before { color: rgba(255, 255, 255, 0.7); }
@media (prefers-reduced-motion: reduce) {
.hfx-tag-cloud, .hfx-tag-cloud *, .hfx-tag-cloud::before, .hfx-tag-cloud::after, .hfx-tag-cloud *::before, .hfx-tag-cloud *::after {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
}
}The same effect using Tailwind utility classes. No custom CSS or config needed.
<ul class="flex max-w-xs flex-wrap items-center justify-center gap-x-1.5 gap-y-1 font-semibold"> <li><a href="#" class="inline-block rounded-full px-2 py-0.5 text-xl transition duration-300 hover:-rotate-6 hover:scale-110 hover:bg-blue-500 hover:text-white hover:shadow-lg hover:shadow-blue-500/40"><span class="text-blue-500">#</span>css</a></li> <li><a href="#" class="inline-block rounded-full px-2 py-0.5 text-sm transition duration-300 hover:rotate-3 hover:scale-110 hover:bg-blue-500 hover:text-white hover:shadow-lg hover:shadow-blue-500/40"><span class="text-blue-500">#</span>animation</a></li> <li><a href="#" class="inline-block rounded-full px-2 py-0.5 text-lg transition duration-300 hover:-rotate-3 hover:scale-110 hover:bg-blue-500 hover:text-white hover:shadow-lg hover:shadow-blue-500/40"><span class="text-blue-500">#</span>design</a></li> <li><a href="#" class="inline-block rounded-full px-2 py-0.5 text-sm transition duration-300 hover:rotate-6 hover:scale-110 hover:bg-blue-500 hover:text-white hover:shadow-lg hover:shadow-blue-500/40"><span class="text-blue-500">#</span>svg</a></li> <li><a href="#" class="inline-block rounded-full px-2 py-0.5 text-lg transition duration-300 hover:rotate-2 hover:scale-110 hover:bg-blue-500 hover:text-white hover:shadow-lg hover:shadow-blue-500/40"><span class="text-blue-500">#</span>motion</a></li> <li><a href="#" class="inline-block rounded-full px-2 py-0.5 text-base transition duration-300 hover:-rotate-6 hover:scale-110 hover:bg-blue-500 hover:text-white hover:shadow-lg hover:shadow-blue-500/40"><span class="text-blue-500">#</span>ui</a></li> </ul>
--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.