Hovering a link pops a small card above it showing where it goes, with a favicon dot and a caret. The URL comes from a data attribute, so each link needs one extra attribute.
Also known as: url preview on hover, link tooltip css, show link destination on hover.
<a class="hfx-link-preview-tooltip" href="#" data-url="example.com/field-notes">Field notes</a>
.hfx-link-preview-tooltip {
--c: var(--hfx-color, #3b82f6);
position: relative;
display: inline-block;
color: var(--c);
font: 600 calc(var(--hfx-size, 16px) * 1.25)/1.3 system-ui, sans-serif;
text-decoration: none;
text-decoration: underline 0.08em color-mix(in srgb, var(--c) 40%, transparent);
text-underline-offset: 0.22em;
transition: text-decoration-color 0.25s ease;}
.hfx-link-preview-tooltip::before,
.hfx-link-preview-tooltip::after {
position: absolute;
left: 50%;
pointer-events: none;
opacity: 0;
transition: opacity 0.2s ease, transform 0.35s cubic-bezier(0.34, 1.56, 0.64, 1);
}
.hfx-link-preview-tooltip::before {
content: "";
bottom: calc(100% + 0.3em);
width: 0.55em;
height: 0.55em;
margin-left: -0.275em;
background: color-mix(in srgb, var(--c) 20%, #111827);
transform: translateY(0.4em) rotate(45deg);
}
.hfx-link-preview-tooltip::after {
content: attr(data-url);
bottom: calc(100% + 0.6em);
padding: 0.55em 0.85em 0.55em 2em;
border: 1px solid color-mix(in srgb, var(--c) 35%, transparent);
border-radius: 0.6em;
background:
radial-gradient(circle at 1.05em 50%, var(--c) 0.3em, transparent 0.34em),
color-mix(in srgb, var(--c) 20%, #111827);
box-shadow: 0 0.5em 1.2em -0.4em rgb(0 0 0 / 0.45);
color: #fff;
font-size: 0.62em;
font-weight: 500;
white-space: nowrap;
transform: translate(-50%, 0.6em) scale(0.94);
transform-origin: 50% 100%;
}
.hfx-link-preview-tooltip:is(:hover, :focus-visible) { text-decoration-color: var(--c); }
.hfx-link-preview-tooltip:is(:hover, :focus-visible)::before {
opacity: 1;
transform: translateY(0) rotate(45deg);
}
.hfx-link-preview-tooltip:is(:hover, :focus-visible)::after {
opacity: 1;
transform: translate(-50%, 0) scale(1);
}
@media (prefers-reduced-motion: reduce) {
.hfx-link-preview-tooltip, .hfx-link-preview-tooltip *, .hfx-link-preview-tooltip::before, .hfx-link-preview-tooltip::after, .hfx-link-preview-tooltip *::before, .hfx-link-preview-tooltip *::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.