Advertisement

Scroll-Triggered Text Highlights

| by Vladimir | 2 min read | code by Ryan Mulligan
A11y Ready Intermediate

Tech & Dependencies

HTML SCSS JavaScript
GSAP ScrollTrigger (GSAP)

Features

  • Scroll-Linked Animation
  • GSAP ScrollTrigger
  • CSS Variables
  • Accessible Highlights
  • Dark Mode

Browser Support

Chrome 60+ Edge 79+ Firefox 60+ Safari 11+

Core

This Scroll-Triggered Text Highlight effect mimics the experience of marking important passages with a highlighter pen as you read. Using GSAP ScrollTrigger, the highlights animate seamlessly from left to right exactly when the text enters the reader’s viewport. The component offers multiple visual styles (full background, half-height, or underline) and fully supports dark mode, making it an excellent addition to long-form articles, documentation, or educational content.

Core Technique

The animation relies on CSS background-size transitions triggered by JavaScript.

  1. CSS Setup: The highlight is created using a linear-gradient set as a background image. Initially, background-size is 0% 100% (invisible width).
  2. Scroll Trigger: The JS code iterates over all elements with the .text-highlight class. It creates a ScrollTrigger for each, watching for when the element’s top edge passes a specific point in the viewport (start: "-100px center").
  3. Activation: When the trigger fires, the class .active is added. The CSS transition then smoothly expands the background-size to 100% 100%, creating the drawing effect.

Customization

The visual style is highly configurable via CSS variables and data attributes.

:root {
  /* Highlight Color */
  --bg-color-highlight: hsl(60, 90%, 50%); /* Yellow */
  
  /* Animation Duration */
  --duration: 1s; 
}

/* Changing the highlight style */
[data-highlight="underline"] .text-highlight {
  --line-size: 0.15em; /* Thickness */
}

To change the trigger point (when the animation starts), adjust the ScrollTrigger config:

ScrollTrigger.create({
  trigger: highlight,
  /* "top 80%" starts when element top hits 80% of viewport height */
  start: "top 80%", 
  onEnter: () => highlight.classList.add("active")
});

Tips

1. Accessibility (A11y): The code cleverly includes pseudo-elements (::before, ::after) with screen-reader-only text: " [highlight start] " and " [highlight end] ". This ensures users navigating via voiceover understand emphasized content, which visual users perceive through color.

2. Decoration Break: The CSS uses box-decoration-break: clone (implied by browser behavior on backgrounds, though explicit support varies). This ensures that if the highlighted text wraps to a new line, the highlight style (padding, border-radius if added) applies correctly to both fragments. Note: The snippet uses background-repeat: no-repeat, which works fine for multiline if the gradient covers the whole box.

Advertisement