Text Highlighter
`<pura-text-highlighter>` is the animated marker pen: a highlighter-color sweep paints the slotted text from one side to the other when it enters the viewport. The trick is a no-repeat `linear-gradient` behind the glyphs whose `background-size` grows from 0% to 100%, so the original text is never duplicated or moved: it stays in the light DOM, selectable and accessible, and `box-decoration-break: clone` keeps the ink continuous across line wraps. `trigger="view"` (default) sweeps once on scroll-in (IntersectionObserver fires a pure CSS transition), `trigger="scrub"` ties the sweep 1:1 to a scroll-driven timeline (`animation-timeline: view()`, zero per-frame JS), `trigger="load"` sweeps on connect. `direction` picks the sweep side, `duration`/`delay` time it, and tokens control the pen: `--pura-text-highlighter-color` (default marker yellow), `--pura-text-highlighter-height` (full block by default, lower it for an underline-style stroke), `--pura-text-highlighter-radius` and `--pura-text-highlighter-padding`. SSR and no-JS paint the full highlight, so the page looks finished without JS; reduced motion lands fully highlighted. Each instance registers in `window.__puraTextHighlighters` by `data-pura-id` with `{ trigger, direction, replay }`.
Preview
<!-- sweeps in once when it enters the viewport (default) -->
<p>
The launch was
<pura-text-highlighter>an absolute success</pura-text-highlighter>
by every metric.
</p>
<!-- scrub tied 1:1 to scroll, thin underline stroke, sweeping leftwards -->
<pura-text-highlighter trigger="scrub" direction="left"
style="--pura-text-highlighter-color: #a5b4fc; --pura-text-highlighter-height: 40%;">
underlined as you scroll
</pura-text-highlighter> Attributes
| Attribute | Type | Default | Description |
|---|---|---|---|
trigger | "view" | "scrub" | "load" | view | view sweeps once when scrolled into view; scrub ties the sweep 1:1 to a scroll-driven timeline; load sweeps once on connect. |
direction | "right" | "left" | right | Which way the pen sweeps across the text. |
duration | number | 900 | Sweep duration in ms (view/load triggers). |
delay | number | 0 | Sweep delay in ms (view/load triggers); stagger multiple highlights with it. |
timeline | "view" | "scroll" | view | Scrub only: view maps the element's own view progress; scroll maps the nearest scroll container. |
range | string | entry 0% cover 50% | animation-range for the scrub timeline. |
Installation
pura is copy-paste and dependency-free. Load the whole library, or just this component.
<link rel="stylesheet" href="/pura/tokens.css">
<script type="module" src="/pura/lib/text-highlighter.js"></script> import "./pura/lib/text-highlighter.js";