title: Highlight Text When a User Scrolls Down to That Piece of Text
url: https://frontendmasters.com/blog/highlight-text-when-a-user-scrolls-down-to-that-piece-of-text/
hash_url: 5ff0fe74d4
archive_date: 2024-03-12
og_image: https://frontendmasters.com/blog/wp-json/social-image-generator/v1/image/639
description: I was reading a great post on Lene Saile’s blog and noticed a cool little design feature on her site that highlights a line of text once you scroll to it. Here’s a video so you can see …
favicon: https://frontendmasters.com/favicon-32x32.png
language: en_US
I was reading a great post on Lene Saile’s blog and noticed a cool little design feature on her site that highlights a line of text once you scroll to it. Here’s a video so you can see what I mean:
The highlighted line is done with a <mark>
element in HTML, which feels right. I noticed the class name on Lene’s implementation is .gsap-highlight
which implies GSAP is used which has as a great Scroll Trigger plugin. Let’s do this without JavaScript though, especially now that I’m hip to Scroll-Driven Animations.
A paragraph with a mark (with a class):
<p>Lorem, ipsum dolor sit amet <mark class="scroll-highlight">consectetur adipisicing elit</mark>. Magnam voluptas aliquid, distinctio voluptatum neque qui modi. In adipisci ratione id officiis nulla veritatis, porro explicabo illum laudantium iure eius velit!</p>
Code language: HTML, XML (xml)
I just want a solid background on the mark. But I’m not going to use background-color
. Instead I’m going to use background-image
, because then I can control the background-size
which I ultimately want to animate. So:
mark.scroll-highlight {
background-size: 100% 100%;
background-repeat: no-repeat;
background-color: transparent;
background-image: linear-gradient(purple, purple);
}
Code language: CSS (css)
Now I can animate that background-size
from 0% 100%
to 100% 100%
which is the look we’re after. It even works when the text breaks across lines which is a miracle.
Now it’s a matter of when to run the animation.
Here’s the whole trick:
mark.scroll-highlight {
background-size: 0 100%;
background-repeat: no-repeat;
background-color: transparent;
background-image: linear-gradient(purple, purple);
animation: mark-it linear;
animation-fill-mode: forwards;
animation-timeline: view();
animation-iteration-count: 1;
animation-range: contain 0% contain 25%;
}
@keyframes mark-it {
0% {
background-size: 0 100%;
}
100% {
background-size: 100% 100%;
}
}
Code language: CSS (css)
The coolest part to me is the animation-range
which gives us the opportunity to say when to start and end the animation with a solid amount of control. In the code above we’re saying to start the animation as soon as the element is fully within the viewport, then finish when it’s 25% of the way up the currently visible viewport.
Remember native support for Scroll-Driven Animations is essentially Chrome ‘n’ friends only right now. You could easily treat this as a progressive enhancement, wrapping the animation stuff in a @supports (animation-timeline: view()) { }
block or however you wanna do it.