text-mask-collage
v0.1.0
Published
Text-driven hero moments made easy: this React component builds a collage of photos, animates them into place, and clips them to the exact outline of your copy.
Readme
Text Mask Collage
Text-driven hero moments made easy: this React component builds a collage of photos, animates them into place, and clips them to the exact outline of your copy.
Installation
npm install text-mask-collageQuick Start
import { TextMaskCollage } from 'text-mask-collage';
const images = Array.from(
{ length: 80 },
(_, index) => `/picsum-images/${String(index + 1).padStart(3, '0')}.jpg`,
);
export default function HeroCollage() {
return (
<TextMaskCollage
text="Create"
images={images}
fontSize="clamp(72px, 12vw, 220px)"
densityFactor={0.7}
jitter={0.15}
maxPhotos={48}
/>
);
}Styles are injected automatically, so there is no extra CSS import.
Props
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| text | string | required | Text that defines the mask |
| images | string[] | required | Array of image URLs used in the collage |
| flyingDuration | number | 1500 | DOM photo travel time (ms) before the SVG layer fades in |
| fadeOutDuration | number | 800 | Fade-out time (ms) for the DOM photos |
| fontSize | string | number | 180 | Font size for the mask text |
| fontFamily | string | "Impact, Arial Black, sans-serif" | Font family for the mask text |
| fontWeight | string | number | 900 | Font weight for the mask text |
| letterSpacing | string | "0.08em" | Letter spacing for the mask text |
| collagePadding | number | 0.3 | Extra padding (relative to text size) applied while laying out the grid |
| photoSize | number | 150 | Base size in pixels for every grid photo |
| densityFactor | number | 1 | Multiplier that compresses grid spacing (lower = denser grid) |
| jitter | number | 0.25 | Random position variance applied per cell (0-0.4) |
| maxPhotos | number | images.length | Hard ceiling for how many photos participate in the animation |
| className | string | "" | Additional CSS class for the wrapper |
| style | CSSProperties | {} | Inline style overrides |
How It Works
- SVG masking: The component measures your text and constructs an SVG clip-path that shapes the final collage.
- Two-stage animation: Photos first fly in via absolutely positioned DOM nodes, then the masked SVG layer fades up while the DOM layer fades away.
- Organic grid:
photoSize,densityFactor, andjittercontrol coverage, overlap, and looseness so you can tune it for different markets or hero layouts. - Once per mount: Layout calculations and image preloading happen when the component mounts, keeping re-renders fast.
Tips
- Smaller
photoSizevalues place more tiles inside the mask; larger values emphasise individual shots. - Lower
densityFactorincreases overlap and fills the mask faster; higher values spread the photos out. maxPhotoscaps how many items join the animation—handy if you want to curb network usage on smaller pages.- Feed the component optimised, cached images (CDN-friendly URLs) for the best perceived performance.
Playground
Clone the repository and run the included Vite playground to experiment locally:
npm install
npm run devA bare-bones HTML prototype is also available at test.html for quick visual checks without React.
License
MIT
