webdevpuneet.com

Marker Highlight Sweep — Animated Text Highlighter in CSS

Marker Highlight Sweep · Text Animation · Plain HTML, CSS & JS · Live preview

Copy & paste

Source Code

<main class="page">
  <article class="note" id="note">
    <p class="meta">Field notes · Issue 12</p>
    <h1>Good design is mostly <mark class="hl yellow">deciding what to leave out</mark>.</h1>
    <p>Before you add another section, ask who it's for. The pages people finish reading usually have <mark class="hl pink">one clear promise</mark>, a headline that says it plainly, and <mark class="hl green">a single next step</mark>. Everything else is noise you are paying for in <mark class="hl blue">attention you don't get back</mark>.</p>
    <button type="button" class="again" id="again">Highlight again</button>
  </article>
</main>

Extend with AI

Take This Snippet Further With AI

Ask an AI coding assistant to explain why the highlight is a background gradient on an inline mark with box-decoration-break: clone and not a pseudo-element, and how the angled gradient with transparent ends creates the felt-pen look. A useful follow-up is how to make the highlight draw from right to left for RTL text.

Prompt to recreate it

Copy this into your AI assistant of choice to build the effect from scratch, or as a jumping-off point for your own variant:

text
Build an animated text-highlighter effect in plain HTML, CSS and JavaScript that works when a highlighted phrase wraps across two lines.

Requirements:
- Use real <mark> elements inside a paragraph and heading. Each gets its colour from a --c custom property, with at least four colour classes.
- Draw the marker as a background-image linear-gradient with a slight angle (about 104 degrees) and soft transparent ends, no-repeat, positioned low in the text line with a background height of about 60%, and set box-decoration-break to clone (also the -webkit- version) so each wrapped line gets its own stripe.
- Animate background-size from 0% to 100% width with a transition of about 0.9s on an ease-in-out curve.
- JavaScript gives each mark a transition delay based on its index so the stripes are drawn one after another in reading order.
- Start the sweep when the article is at least 40% visible using an IntersectionObserver (with a fallback that starts immediately), and add a button that restarts it by removing the class, forcing a reflow and re-adding it.
- Under prefers-reduced-motion, show the finished highlights with no transition.

Want to tighten it up first? Run this prompt through the AI Prompt Studio to score it across 8 quality dimensions, catch anti-patterns, and tune the wording for Claude, ChatGPT, or Gemini before you paste it in.

What's included

Features

Wraps across lines
box-decoration-break: clone makes every line fragment of a long phrase draw its own complete stripe.
Hand-drawn stripe
A 104° gradient with soft transparent ends and slight overshoot looks like a felt-tip pen instead of a flat rectangle.
Staggered in reading order
Each highlight gets its own delay from its index, so the sweep follows the way the text is read.
Starts when visible
An IntersectionObserver waits until the note is on screen, with a plain fallback for older browsers.
Four colours via one variable
--c sets each marker colour, so adding a fifth is one extra class.
Semantic and motion-safe
Uses the real <mark> element, and reduced-motion visitors see the finished highlights instantly.

About this UI Snippet

Marker Highlight Sweep — Animated Background Gradient Highlight That Survives Line Wraps

Screenshot of the Marker Highlight Sweep snippet rendered live

Highlighting the important phrase in a paragraph is an editor's habit, and animating it makes a reader's eye land on it. The trick with highlights on the web is that most approaches break when the phrase spans two lines. This one is built to wrap: each marked phrase is an inline <mark> whose background is a gradient that grows from 0 to 100% width, with box-decoration-break: clone so every line fragment gets its own full stripe.

A gradient that looks hand-drawn

The marker is linear-gradient(104deg, transparent .9%, colour 2.4%, colour 97%, transparent 99%). The slight 104° angle and the soft transparent ends round the stripe's tips like a real felt tip, and background-position: 0 78% with background-size: 100% 62% sits it low across the lower two-thirds of the text rather than blanketing it. Negative horizontal margin and small padding let the stripe extend a bit past the words, like overshoot.

Animating background-size, with a staggered pen

Each highlight transitions background-size from 0% 62% to 100% 62% over 0.9s on an ease-in-out curve. JavaScript gives every mark a delay of 0.4 + 0.9 × index seconds, in reading order, so the effect feels like one pen moving through the text. An IntersectionObserver starts it only when the note is 40% visible, so readers don't miss it above the fold.

Accessible and re-runnable

<mark> is the correct semantic element for highlighted text, and screen readers can announce it. The text is fully readable before and after the sweep, and reduced-motion visitors get the finished highlights immediately. The button restarts the sweep by clearing the class and forcing a reflow.

Step by step

How to Use

  1. 1
    Paste the blocksA paper-coloured article renders with four phrases highlighted in yellow, pink, green and blue, sweeping in one after another once the note scrolls into view.
  2. 2
    Mark your own phrasesWrap any text in <mark class="hl yellow">…</mark>. Pick yellow, pink, green or blue, or define a new colour with the --c custom property.
  3. 3
    Set the pen speedThe 0.9s in the CSS is each stripe's duration; the 0.9 in the JS is the gap between stripes. Make them equal for a continuous stroke, or smaller for overlapping marks.
  4. 4
    Change the stripe shapeAdjust the 62% height and the 78% vertical position for a thinner underline-style marker or a full-height block.
  5. 5
    Highlight on a different triggerCall sweep() from a button, tab change, or hover on a parent card instead of the observer.

Real-world uses

Common Use Cases

Blog posts and long reads
Highlight the one sentence a skimmer should not miss, a pull-quote or a key statistic in an article.
Landing page value propositions
Underline "free forever" or "no card needed" in a hero paragraph without adding a badge.
Course and learning pages
Mark the terms a lesson introduces, so students can see the vocabulary in context.
Newsletters and editorial layouts
Give editorial pieces a magazine-like emphasis without images or custom fonts.
Case study results
Highlight the results ("cut load time by 63%") inside a longer narrative paragraph.

Got questions?

Frequently Asked Questions

A pseudo-element is a single box, so it can't follow a phrase onto a second line. A background on an inline element with box-decoration-break: clone is the reliable way to get a stripe per line.

Make sure box-decoration-break: clone and the -webkit- version are both set, and that the mark is display: inline (not inline-block).

Yes, but swap the text colour and pick stripe colours with enough contrast against it. Mid-tone or neon-ish colours with dark text read better than pastels on dark backgrounds.

More than three or four in one screen dilutes the effect. A highlight works because it is rare; if everything is marked, nothing stands out.