webdevpuneet.com

SVG Mask Sweep Text Reveal — Clip-Path Wipe Animation

SVG Mask Sweep Text Reveal · Animations · Plain HTML, CSS & JS · Live preview

CategoryAnimations

Copy & paste

Source Code

<div class="scene">
  <h1 class="sweep-heading" onclick="playSweep()">Reveal on demand</h1>
  <p class="hint">Click the headline to sweep the reveal shape across it again</p>
  <svg width="0" height="0" style="position:absolute">
    <defs>
      <mask id="sweepMask" maskUnits="objectBoundingBox">
        <rect x="0" y="0" width="1" height="1" fill="black" />
        <ellipse id="sweepShape" cx="-0.25" cy="0.5" rx="0.22" ry="0.9" fill="white" />
      </mask>
    </defs>
  </svg>
</div>

Extend with AI

Take This Snippet Further With AI

The AI prompt for this one is for Patreon supporters ($3 a month), along with a site with no ads. Supporters enter the passcode once and it is remembered in this browser.

· Become a supporter

What's included

Features

Uses a real SVG <mask> element, not CSS clip-path — supports soft, feathered edges
maskUnits="objectBoundingBox" makes the mask scale correctly to any text size automatically
CSS mask property applies the SVG mask directly to an ordinary HTML heading element
Sweep is driven by animating the ellipse's own cx attribute, not a CSS transform
Instant reset via transition: none plus a forced layout read prevents a visible snap-back
Shape starts and ends fully outside the bounding box for a clean, uninterrupted sweep
Click-to-replay demo trigger — easily swapped for hover, load, or scroll triggers
Works with any text length or wrapping since the mask geometry is bounding-box relative
Export as HTML file, React JSX, or React + Tailwind CSS
Mobile (375px), Tablet (768px), Desktop device preview buttons

About this UI Snippet

SVG Mask Sweep Text Reveal — Animated <mask> Shape, Not clip-path

Screenshot of the SVG Mask Sweep Text Reveal snippet rendered live

An SVG mask sweep reveals a headline by moving a shape — here a tall, narrow ellipse — through an SVG <mask> referenced by the heading's own mask CSS property, so the text appears wherever the shape currently overlaps it, like a spotlight passing across a dark room. This is a different mechanism from a CSS clip-path scroll-driven reveal: a <mask> supports soft, blurred, and gradient-edged shapes (not just hard polygon boundaries), and moving an SVG shape's own geometric attribute produces a smoother, more organic sweep than animating clip-path polygon coordinates directly. Trigger it on click, hover, or page load — this demo replays on click so you can see the sweep repeatedly.

The SVG mask structure

Inside <defs>, a <mask id="sweepMask" maskUnits="objectBoundingBox"> contains two shapes: a full-size black <rect> covering the entire bounding box (mask value 0 = fully hidden) and a white <ellipse id="sweepShape"> (mask value 1 = fully visible) positioned at cx="-0.25" — just outside the left edge of the box. maskUnits="objectBoundingBox" means every coordinate in the mask is expressed as a fraction of the masked element's own size (0 to 1), so the mask works correctly regardless of the heading's actual pixel dimensions or how the text reflows at different widths.

Applying the mask to HTML text

mask: url(#sweepMask) (with the -webkit- prefix for Safari) applies the SVG mask directly to the <h1> element as a CSS property — this works on ordinary HTML elements, not just SVG shapes, because CSS Masking is a separate spec from SVG that happens to be able to reference SVG <mask> definitions by ID. Wherever the mask is white, the heading is visible; wherever it is black, the heading is invisible; the soft edge of the ellipse (versus a hard polygon edge) naturally anti-aliases into a slightly feathered reveal boundary.

Animating the shape's own attribute, not a CSS property

playSweep() directly sets the ellipse's cx attribute — first snapping it back to -0.25 with transition: none (so the reset is instant and invisible), forcing a layout read via shape.getBoundingClientRect() to flush that instant snap, then re-enabling a cx transition and setting cx to 1.25 (past the right edge) on the next animation frame. Because cx is animated as a plain SVG presentation attribute rather than a CSS transform, this technique works even in contexts where transforming a mask's internal shape via CSS transforms is unreliable across browsers — animating the geometry attribute directly is the more portable choice for SVG mask content.

Why 1.25 and -0.25, not 0 and 1

Starting the ellipse's center at -0.25 (rather than 0) and ending at 1.25 (rather than 1) ensures the shape's full width — including its rx="0.22" radius — is completely outside the bounding box at both the start and end of the animation, so the sweep begins and ends on a fully hidden and fully revealed headline respectively, with no shape edge visibly clipped by the box boundary mid-transition.

Step by step

How to Use

  1. 1
    Click the headlineClick the heading text to replay the mask sweep — a tall ellipse shape moves left to right, revealing the text as it passes.
  2. 2
    Change the headline textEdit the text inside .sweep-heading in the HTML panel.
  3. 3
    Change the sweep shapeIn the HTML panel, adjust rx and ry on #sweepShape — a smaller rx makes a narrower, more spotlight-like sweep; a larger one reveals more of the text at once.
  4. 4
    Change the sweep speedIn the JS panel, update 1.1s inside the transition string set on shape.style.transition.
  5. 5
    Trigger on scroll instead of clickWrap the playSweep() call in an IntersectionObserver (see the pattern in char-flip-reveal-3d) instead of an onclick handler.
  6. 6
    Export in your formatClick "HTML" for a standalone file, "JSX" for a React component, or "Tailwind" for a React + Tailwind version.

Real-world uses

Common Use Cases

Hero headline reveal on page load
Trigger playSweep() once on load instead of on click for a headline that reveals itself as the page finishes rendering, similar in spirit to a curtain-opening reveal.
Portfolio and case-study section transitions
Use the sweep to reveal a section heading as it enters the viewport, giving a case study or portfolio page a considered, editorial pacing.
Learn SVG mask vs clip-path for text reveals
Compare this snippet with a clip-path-based reveal to see how mask supports soft edges and reusable objectBoundingBox coordinates that clip-path polygons cannot easily replicate.
Click-to-reveal interactive headlines
Keep the click-to-replay trigger as-is for an interactive element where hovering or clicking a headline rewards the visitor with a satisfying sweep animation.
Pair with a scroll-triggered observer
Combine with the IntersectionObserver pattern from 3D character flip reveal to fire the sweep automatically as the heading scrolls into view instead of requiring a click.
Product feature spotlight callouts
Use a tighter, narrower ellipse as a genuine "spotlight" that sweeps across a feature name, drawing deliberate attention to one phrase within a longer sentence.

Got questions?

Frequently Asked Questions

clip-path only supports hard-edged geometric shapes (polygons, circles, insets) with no blur or feathering, and moving one requires animating its shape function's coordinates directly in CSS. An SVG mask can use any SVG content — including shapes with blur filters, gradients, or soft edges — and this snippet animates the mask shape's own geometric attribute (cx) rather than a CSS clip-path string, which is more flexible for organic-feeling sweeps.

It makes every coordinate inside the mask (0 to 1) relative to the masked element's own bounding box rather than absolute pixel values. This means the same mask definition works correctly no matter how wide the heading text actually renders — the sweep shape's position and size scale automatically with the element it is masking.

Without disabling the transition first, resetting cx back to its starting position would itself animate backward across the text, visibly undoing the reveal before the real sweep begins. Setting transition: none makes the reset instant and invisible, and the forced getBoundingClientRect() read flushes that change before the transition is re-enabled for the actual sweep.

The ellipse has its own radius (rx="0.22"), so if its center only moved from 0 to 1, part of the shape would still be visible inside the box even at the very start and end of the sweep. Starting and ending 0.25 outside the 0-1 range guarantees the shape is fully clear of the box at both endpoints.

Yes — animate the ellipse's cy attribute instead of cx, and adjust rx/ry so the shape is wide and short instead of tall and narrow, so it sweeps top to bottom across the text.

Yes. Click "JSX" for a React component. Render the SVG mask definition once, reference it via the mask CSS property on the heading (mask: "url(#sweepMask)"), and drive the ellipse's cx with a ref and the same transition-reset-then-set technique inside a triggered function.