Animated Scroll Highlight Annotations
See the Pen Animated Scroll Highlight Annotations.
Tech & Dependencies
Features
- ✓ Scroll Highlights
- ✓ Theme Toggle
- ✓ Fallback Support
Browser Support
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 utilizesIntersectionObserverto 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 HTMLdata-authorattributes. - Responsiveness: Fluid text scaling using standard
remunits. 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()")anddocument.startViewTransition). In unsupported browsers, the theme switches instantly without the masking animation, and the text highlights gracefully fall back to theIntersectionObserverlogic.
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-positiontransitions for the<mark>elements. It houses the@supportsqueries for experimental CSS timelines. - JS: The state manager. It handles the
aria-pressedlogic for the theme button, initiates thestartViewTransitionAPI, and deploys theIntersectionObserverfallback 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.


