Back in the halcyon days, before TikTok, NFTs, and Conde Nast gutting Wired Magazine like a Thanksgiving turkey, their website utilized this blue highlighter underline effect for hyperlinks that I always found attractive.
What if we took that but applied a modern makeover by making it seem as if some invisible, digital elf was highlighting them in real-time as we scrolled down the page?
Like this! (I'm sure you already saw it but let's just pretend it was a well-timed reveal)
Anyway, the implementation is pretty trivial.
First some CSS. The effect here is just a background image, shaped using linear-gradient to mimic the look of a underline, and then animating it across using CSS transitions when the active class is added to it.
:root {
--color-text-highlight: #333;
--bg-color-highlight: #87d49a;
--bg-color-highlight-hover: #a1e3b2;
--line-size: 0.25em;
--ease: cubic-bezier(0.30, 1, 0.5, 1);
--duration: 1.5s;
}
.digital-elf-link {
background-repeat: no-repeat;
background-size: 0% 100%;
cursor: pointer;
font-weight: 300;
color: #000;
background-image: linear-gradient(
transparent calc(100% - var(--line-size)),
var(--bg-color-highlight) var(--line-size)
);
transition:
background-color calc(var(--duration) / 4) var(--ease),
background-size var(--duration) var(--ease);
&.active {
background-size: 100% 100%;
}
&:hover {
background-image: linear-gradient(
transparent calc(100% - var(--line-size)),
var(--bg-color-highlight-hover) var(--line-size)
);
}
}
And for that, we'll use GSAP. Let's create a custom hook and toss our GSAP code in there. ScrollTrigger has a light lift here, only being leveraged to 'activate' the links as they appear so CSS can work its magic.
// useLinkHighligher.js
import { gsap } from 'gsap';
import { ScrollTrigger } from 'gsap/ScrollTrigger';
import { useGSAP } from '@gsap/react';
gsap.registerPlugin(ScrollTrigger);
const useLinkHighlighter = () => {
useGSAP(() => {
const highlights = gsap.utils.toArray("p .digital-elf-link");
highlights.forEach((highlight) => {
ScrollTrigger.create({
start: "-120px center",
trigger: highlight,
onEnter: () => highlight.classList.add("active")
});
});
}, []);
};
export default useLinkHighlighter;
From there, just import, call, and Bob's your uncle. Happy highlighting.
import useLinkHighlighter from "@/src/lib/useLinkHighlighter";
// ...
useLinkHighlighter();