SolutionsCase StudiesAI ToolsResourcesAboutContact
Get Your Free AI Automation Audit Book a Free 30-Minute Strategy Call
Playground~/frontend Open editor

~/css/link-hover-effects

7 CSS Link Hover Effects

6 Pure CSS1 with JSPublished 2026-10-05Free · no sign-up

Seven link styles: an underline that grows in from the left and leaves to the right, a highlight that rises behind the words, a call to action with a moving arrow, a native underline that shifts and thickens, an external link marker, a nav with a sliding pill and a dotted underline for glossary terms.

01. Underline Grows In, Exits Out

LinkUnderline

The underline grows from the left on hover and leaves to the right when the pointer moves away, which feels like it passed through. The trick is changing transform-origin between the two states, so each direction scales from a different side.

View code
<p class="lk1">Read our <a href="#guide">shipping guide</a> before you order.</p>
.lk1 { margin: 0; color: #344054; font: 18px Inter, system-ui, sans-serif; }
.lk1 a { position: relative; color: #1d4ed8; font-weight: 600; text-decoration: none; }
.lk1 a::after { content: ""; position: absolute; left: 0; right: 0; bottom: -2px; height: 2px; background: currentColor; transform: scaleX(0); transform-origin: right; transition: transform .3s ease; }
.lk1 a:hover::after, .lk1 a:focus-visible::after { transform: scaleX(1); transform-origin: left; }
.lk1 a:focus-visible { outline: 2px solid #1d4ed8; outline-offset: 3px; border-radius: 2px; }
@media (hover: none) { .lk1 a { text-decoration: underline; } .lk1 a::after { display: none; } }

02. Highlight Rises Behind the Link

LinkBackground

A thin coloured underline at rest becomes a full highlight behind the text on hover, because the background gradient's height animates from 2px to 100 percent. The text colour stays dark on the pale highlight for contrast.

View code
<p class="lk2">Browse the <a href="#archive">full archive</a> or <a href="#search">search</a>.</p>
.lk2 { margin: 0; color: #344054; font: 18px Inter, system-ui, sans-serif; }
.lk2 a { color: #101828; font-weight: 600; text-decoration: none; background: linear-gradient(#a7f3d0, #a7f3d0) 0 100% / 100% 2px no-repeat; transition: background-size .25s ease; }
.lk2 a:hover, .lk2 a:focus-visible { background-size: 100% 100%; }
.lk2 a:focus-visible { outline: 2px solid #059669; outline-offset: 2px; }
@media (prefers-reduced-motion: reduce) { .lk2 a { transition: none; } }

03. Link with Moving Arrow

LinkIcon

A standalone call-to-action link whose arrow nudges right on hover, hinting at going somewhere. The arrow is an aria-hidden span so the accessible name is just the words, and the movement is a transform on the arrow only.

View code
<a class="lk3" href="#case-study">Read the case study <span aria-hidden="true">&rarr;</span></a>
.lk3 { display: inline-flex; align-items: center; gap: 6px; color: #93c5fd; font: 700 17px Inter, system-ui, sans-serif; text-decoration: none; }
.lk3 span { transition: transform .25s ease; }
.lk3:hover span, .lk3:focus-visible span { transform: translateX(5px); }
.lk3:hover { color: #bfdbfe; }
.lk3:focus-visible { outline: 2px solid #93c5fd; outline-offset: 3px; border-radius: 3px; }
@media (prefers-reduced-motion: reduce) { .lk3 span { transition: none; } }

04. Underline Offset Shift

LinkUnderline

A native text underline that moves closer and thickens on hover, using text-underline-offset and text-decoration-thickness. Real underlines respect descenders with text-decoration-skip-ink, which a pseudo-element underline cannot do.

View code
<p class="lk4">Questions? <a href="#help">Visit the help centre</a> or reply to any email.</p>
.lk4 { margin: 0; color: #344054; font: 18px Inter, system-ui, sans-serif; }
.lk4 a { color: #6d28d9; font-weight: 600; text-decoration: underline; text-decoration-color: #c4b5fd; text-decoration-thickness: 1px; text-underline-offset: 6px; text-decoration-skip-ink: auto; transition: text-underline-offset .2s, text-decoration-thickness .2s, text-decoration-color .2s; }
.lk4 a:hover, .lk4 a:focus-visible { text-underline-offset: 3px; text-decoration-thickness: 3px; text-decoration-color: #6d28d9; }
.lk4 a:focus-visible { outline: 2px solid #6d28d9; outline-offset: 3px; border-radius: 2px; }

05. External Link with Icon

LinkExternal

Links to other sites get a small arrow-out icon that lifts on hover, added automatically with an attribute selector on href^="http". A visually hidden note says it opens another website, which matters when the link leaves your site.

View code
<p class="lk5">Built with <a href="https://developer.mozilla.org/">MDN's guides<span class="sr"> (external site)</span></a> as reference.</p>
.lk5 { margin: 0; color: #cbd5e1; font: 17px Inter, system-ui, sans-serif; }
.lk5 a { color: #67e8f9; font-weight: 600; text-underline-offset: 3px; }
.lk5 a[href^="http"]::after { content: "↗"; display: inline-block; margin-left: 2px; font-size: .8em; transition: transform .2s ease; }
.lk5 a[href^="http"]:hover::after, .lk5 a[href^="http"]:focus-visible::after { transform: translate(2px, -2px); }
.lk5 .sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); }
.lk5 a:focus-visible { outline: 2px solid #67e8f9; outline-offset: 2px; border-radius: 2px; }
@media (prefers-reduced-motion: reduce) { .lk5 a::after { transition: none; } }

06. Nav Links with a Sliding Pill

LinkNavigation

A pill-shaped highlight slides between nav links to follow the hovered or focused one, and settles on the current page when the pointer leaves. A few lines of script measure the link and move one absolutely positioned pill with transform.

View code
<nav class="lk6" aria-label="Main"><span class="pill" aria-hidden="true"></span><a href="#home" aria-current="page">Home</a><a href="#pricing">Pricing</a><a href="#blog">Blog</a><a href="#contact">Contact</a></nav>
.lk6 { position: relative; display: flex; gap: 2px; padding: 5px; border: 1px solid #e4e7ec; border-radius: 999px; background: #fff; font: 600 14px Inter, system-ui, sans-serif; }
.lk6 a { position: relative; z-index: 1; padding: 8px 12px; border-radius: 999px; color: #344054; text-decoration: none; }
.lk6 a[aria-current] { color: #101828; }
.lk6 .pill { position: absolute; top: 5px; left: 0; height: calc(100% - 10px); border-radius: 999px; background: #f2f4f7; transition: transform .3s cubic-bezier(.2,.8,.2,1), width .3s cubic-bezier(.2,.8,.2,1); }
.lk6 a:focus-visible { outline: 2px solid #528bff; outline-offset: 1px; }
@media (prefers-reduced-motion: reduce) { .lk6 .pill { transition: none; } }
var nav = document.querySelector('.lk6'), pill = nav.querySelector('.pill'), cur = nav.querySelector('[aria-current]');
function to(a) { pill.style.width = a.offsetWidth + 'px'; pill.style.transform = 'translateX(' + a.offsetLeft + 'px)'; }
nav.querySelectorAll('a').forEach(function (a) { a.addEventListener('mouseenter', function () { to(a); }); a.addEventListener('focus', function () { to(a); }); });
nav.addEventListener('mouseleave', function () { to(cur); }); nav.addEventListener('focusout', function (e) { if (!nav.contains(e.relatedTarget)) to(cur); });
to(cur);

07. Dotted Underline Turns Solid

LinkGlossary

A glossary-style term with a dotted underline that turns solid and changes colour on hover, a convention readers recognise as a definition link. It uses text-decoration-style, so it wraps across lines correctly, unlike a border-bottom.

View code
<p class="lk7">Our checkout passes <a href="#glossary-pci">PCI DSS</a> checks every quarter.</p>
.lk7 { margin: 0; color: #cbd5e1; font: 17px Inter, system-ui, sans-serif; }
.lk7 a { color: #fde68a; text-decoration: underline dotted #fde68a; text-decoration-thickness: 2px; text-underline-offset: 4px; transition: color .2s, text-decoration-color .2s; }
.lk7 a:hover, .lk7 a:focus-visible { color: #fbbf24; text-decoration-style: solid; text-decoration-color: #fbbf24; }
.lk7 a:focus-visible { outline: 2px solid #fbbf24; outline-offset: 2px; border-radius: 2px; }

About these CSS Link Hover Effects

Links in text must look like links

Inside a paragraph, colour alone is not enough to mark a link for people who cannot tell colours apart. Keep an underline at rest, or a 3:1 contrast difference with the surrounding text plus a hover change.

Native underlines are smarter

text-decoration skips descenders with text-decoration-skip-ink and wraps across lines. Tune it with text-underline-offset and text-decoration-thickness before reaching for a pseudo-element.

Direction from transform-origin

To make an underline grow from the left and leave to the right, set transform-origin: left on hover and right at rest. The browser scales from whichever side the current state names.

Say when a link leaves the site

A small arrow-out icon added with a[href^="http"]::after shows external links, and hidden text such as external site tells screen reader users too.

Frequently asked questions

Should links open in a new tab?

Usually not. Let people choose; if you must, say so in the link text.

What about visited links?

Style :visited with a slightly different colour on content-heavy sites; it helps readers track where they have been.

Do the effects work for focus?

Yes. Every hover style also applies on :focus-visible, with a visible outline.