motion-text-mask

Mask-clip reveal primitive. Clips slotted content behind an overflow:hidden boundary and springs it upward into view. This is the same technique used inside motion-headline, exposed as a standalone composable wrapper for any content.

Preview

Revealed from below

Import

import 'motion-components/motion-text-mask'   // just this one
import 'motion-components'               // or the whole library

Usage

<motion-text-mask>
  Your headline or any block content
</motion-text-mask>

Composing with motion-stagger

Wrap each line or word in its own motion-text-mask inside a motion-stagger to build a custom headline reveal without using motion-headline.

Craft award-winning motion.
<motion-stagger interval="0.1">
  <motion-text-mask>Craft</motion-text-mask>
  <motion-text-mask>award-winning</motion-text-mask>
  <motion-text-mask>motion.</motion-text-mask>
</motion-stagger>

How it works

The host element has overflow:hidden set via Shadow DOM styles and vertical-align:bottom so the clip boundary sits at the text baseline. An inner div starts at translateY(110%) (the extra 10% prevents sub-pixel bleed-through) and spring-animates to translateY(0%). The content appears to rise from behind an invisible floor.

Loop

Add loop to rise the text into view, hold, drop it back behind the mask and rise again. hold sets how long it stays visible, gap how long it stays hidden.

Rises and falls with the mask.

<motion-text-mask loop hold="1.4" gap="0.5">the mask</motion-text-mask>

The cycle runs only while the text is on screen, and once is ignored. Add pause-on-hover to freeze it while the pointer is over the text.

Properties

Attribute Property Type Default Description
duration duration number 0.9 Spring duration hint in seconds
delay delay number 0 Initial delay in seconds before the reveal
threshold threshold number 0.2 IntersectionObserver visibility threshold (0–1)
once once boolean true Reveal only on first intersection. Ignored with loop
loop loop boolean false Reveal, hold, hide and reveal again on repeat. The cycle runs while the text is on screen
hold hold number 1.6 With loop, seconds the text stays visible before it hides
gap gap number 0.5 With loop, seconds the text stays hidden before it reveals again
pause-on-hover pauseOnHover boolean false Pause the loop while the pointer is over the text, resuming on leave

JavaScript API

Trigger the text mask programmatically with play() and cancel().

JavaScript API
–

Accessibility

Respects prefers-reduced-motion: when enabled, the mask reveal animates instantly, the text is fully visible and loop never starts.