Travelling Underline
Hover a link and the line grows in from the left. Leave it, and the line keeps going out to the right instead of rewinding back the way it came.
Everything since 2019 lives in .
Give my links an underline that travels instead of rewinding. The colours, sizes and wording are listed at the end; use those exact values. The mistake to avoid first: almost every hand-built link animates the underline in from the left and then retracts it back to the left when the pointer leaves. It looks like a mistake being undone. A considered link lets the line continue through and exit the far side. Build it with a single pseudo-element, not with text-decoration and not by animating width. The link itself is position: relative, text-decoration: none, and carries the underline offset as bottom padding. Its ::after is absolutely positioned at left: 0, right: 0, bottom: 0, with the given thickness and colour, and transform: scaleX(0). The resting rule sets transform-origin: right center. The hover rule sets transform: scaleX(1) and transform-origin: left center. That pair is the entire effect. transform-origin is not animated, so on the way in the line grows from the left edge, and the moment the pointer leaves, the rule reverts and the line collapses toward the right edge, which reads as the line continuing on its way out. Transition transform only, over the given travel time, with an ease-out curve like cubic-bezier(0.22, 1, 0.36, 1). Do not animate width or background-size: those relayout or repaint every frame, while a scaleX transform is composited and stays smooth on long links and slow phones. Apply the same rule to :focus-visible as to :hover, and give the link a real focus outline offset a few pixels from the text. A hover-only underline leaves keyboard users with nothing. A link marked aria-current="page" keeps its underline permanently at about 35% opacity, parked at the left origin so it does not animate on page load. That is a state, not a hover. Under prefers-reduced-motion, stop moving the line: leave it at full width and cross-fade its opacity instead. One caution about where this belongs. This pattern is for navigation and standalone links. Links inside long body copy should stay underlined at rest, because an underline that only appears on hover is invisible to anyone scanning the paragraph. Make it mine: - Make the underline 1.5px thick. - Sit the underline 3px below the text. - Use "the full archive" as the inline link inside the sentence. - Use "Selected work" as the first standalone link. - Use "Get in touch" as the second standalone link. Build the component, not this demo of it. - Ambient motion that IS the component may loop: a drifting background, a marquee, a spinner while something is genuinely loading. - Do not add any timer, interval, loop or script that performs a person's action by itself. No auto-hover, no auto-click, no cycling through states, no pretend submitting, no replaying the interaction on a schedule. - Every state that answers a person waits for a real event from that person. - Placeholder copy and sample content are welcome. Simulated behaviour is not.