Advertisement

Animated Scroll Highlight Annotations

| by Vladimir | 3 min read | code by Jhey
Intermediate

Tech & Dependencies

HTML CSS JavaScript

Features

  • Scroll Highlights
  • Theme Toggle
  • Fallback Support

Browser Support

Chrome 115+ Edge 115+ Firefox 55+ (via fallback) Safari 26.0+

Core

This is an Animated Scroll Highlight Annotations component. It combines a spatial theme toggle with progressive reading indicators that colorfully highlight key text passages as they enter the viewport. Its function is to enhance long-form reading experiences by guiding the user’s eye to critical information through contextual, scroll-bound motion.

Specs

  • Weight: ~3 KB. Zero dependencies.
  • Performance: High. The highlight effect is natively driven by CSS animation-timeline: view() where supported, pushing calculations to the compositor thread. The JavaScript fallback utilizes IntersectionObserver to toggle a CSS custom property, avoiding heavy continuous scroll event listeners.
  • Theming / Customization: Theme toggling leverages native CSS inheritance. The marker colors and author badges are controlled via inline CSS variables (--hue) and HTML data-author attributes.
  • Responsiveness: Fluid text scaling using standard rem units. Automatically adapts to viewport height changes.
  • Web APIs: Intersection Observer, View Transitions API.
  • Graceful Degradation: Flawless. Implements strict feature detection (CSS.supports("animation-timeline: view()") and document.startViewTransition). In unsupported browsers, the theme switches instantly without the masking animation, and the text highlights gracefully fall back to the IntersectionObserver logic.

Anatomy

  • HTML: A semantic structure primarily using <main>, <section>, <p>, and <mark>. The theme toggle is an accessible <button aria-pressed="true">.
  • CSS: The visual core. Defines the structural grid, dark/light mode color tokens, and the complex background-position transitions for the <mark> elements. It houses the @supports queries for experimental CSS timelines.
  • JS: The state manager. It handles the aria-pressed logic for the theme button, initiates the startViewTransition API, and deploys the IntersectionObserver fallback loop for older browsers.

Logic

The architectural highlight is the seamless blending of bleeding-edge CSS with a robust JavaScript fallback for the text reveal.

@supports (animation-timeline: view()) {
  mark {
    --highlighted: 0;
    animation: highlight steps(1) both;
    animation-timeline: view();
    animation-range: entry 100% cover 10%;
  }
}
// Fallback for unsupported browsers
if (!CSS.supports("animation-timeline: view()")) {
  const HANDLE = (entries) => {
    entries.forEach((entry) => {
      entry.target.style.setProperty("--highlighted", entry.isIntersecting ? 1 : 0);
    });
  };
  const OBSERVER = new IntersectionObserver(HANDLE, { threshold: 1.0 });
}

Instead of duplicating animation logic across CSS and JS, the author centralizes the visual transition inside the CSS mark span selector, which listens to the --highlighted variable. Modern browsers let the CSS view() timeline toggle this variable from 0 to 1 natively. If the browser fails the @supports check, the JS IntersectionObserver simply steps in to update that exact same --highlighted variable when the element intersects the viewport. The rendering pipeline remains perfectly synchronized regardless of the underlying mechanism.

Feel

Editorial and polished. As you scroll down the page, the highlighted markers reveal themselves with a smooth, directional wipe, mimicking the physical stroke of a highlighter pen. The author badges pop into existence with a subtle scale transition, adding a layer of conversational context. Triggering the theme toggle unleashes a dramatic, expanding polygon mask over the entire interface, making the context switch feel deliberate and spatial rather than jarring.

Advertisement