Quiet footer links that brighten on hover while an arrow slides in from the left and nudges the label over. The arrow is absolutely placed, so the list never reflows.
Also known as: footer link hover, arrow slide in link, text shift arrow hover.
<div class="hfx-link-arrow-reveal"> <a href="#"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M4 12h15m-6-6 6 6-6 6"/></svg><span>Careers</span></a> <a href="#"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M4 12h15m-6-6 6 6-6 6"/></svg><span>Press kit</span></a> <a href="#"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M4 12h15m-6-6 6 6-6 6"/></svg><span>Contact</span></a> </div>
.hfx-link-arrow-reveal {
--c: var(--hfx-color, #3b82f6);
display: flex;
flex-direction: column;
align-items: flex-start;
gap: 0.35em;
font: 500 calc(var(--hfx-size, 16px) * 1.15)/1.4 system-ui, sans-serif;
}
.hfx-link-arrow-reveal a {
position: relative;
display: inline-flex;
align-items: center;
padding-right: 1.1em;
color: inherit;
opacity: 0.65;
text-decoration: none;
transition: opacity 0.25s ease, color 0.25s ease;
}
.hfx-link-arrow-reveal svg {
position: absolute;
left: 0;
width: 0.85em;
height: 0.85em;
fill: none;
stroke: var(--c);
stroke-width: 2.4;
stroke-linecap: round;
stroke-linejoin: round;
opacity: 0;
transform: translateX(-0.6em);
transition: opacity 0.25s ease, transform 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);
}
.hfx-link-arrow-reveal span { transition: transform 0.3s cubic-bezier(0.34, 1.56, 0.64, 1); }
.hfx-link-arrow-reveal a:is(:hover, :focus-visible) {
opacity: 1;
color: var(--c);
}
.hfx-link-arrow-reveal a:is(:hover, :focus-visible) svg {
opacity: 1;
transform: translateX(0);
}
.hfx-link-arrow-reveal a:is(:hover, :focus-visible) span { transform: translateX(1.1em); }
@media (prefers-reduced-motion: reduce) {
.hfx-link-arrow-reveal, .hfx-link-arrow-reveal *, .hfx-link-arrow-reveal::before, .hfx-link-arrow-reveal::after, .hfx-link-arrow-reveal *::before, .hfx-link-arrow-reveal *::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.
<div class="flex flex-col items-start gap-1.5 text-lg">
<a href="#" class="group relative inline-flex items-center pr-5 opacity-60 transition hover:text-blue-500 hover:opacity-100">
<span class="absolute left-0 -translate-x-2 opacity-0 transition group-hover:translate-x-0 group-hover:opacity-100" aria-hidden="true">→</span>
<span class="transition-transform duration-300 group-hover:translate-x-5">Careers</span>
</a>
<a href="#" class="group relative inline-flex items-center pr-5 opacity-60 transition hover:text-blue-500 hover:opacity-100">
<span class="absolute left-0 -translate-x-2 opacity-0 transition group-hover:translate-x-0 group-hover:opacity-100" aria-hidden="true">→</span>
<span class="transition-transform duration-300 group-hover:translate-x-5">Press kit</span>
</a>
</div>--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.