A smooth, responsive web animation that uses PNG frame sequences to create a mask reveal effect. Click a button to reveal hidden content through an animated mask that expands from the button's position.
- Frame-based Animation: Uses 30 PNG frames for both reveal (in) and hide (out) sequences
- Mobile Optimized: Automatically loads smaller 1024x1024 images on mobile to prevent memory crashes
- Smooth Performance: All frames preloaded before interaction, ensuring lag-free animation
- Cross-browser Compatible: Uses SVG masks on desktop, CSS masks on mobile for maximum compatibility
- Responsive Design: Works seamlessly across desktop and mobile devices
├── index.html # Main HTML page
├── styles.css # CSS styles and mask definitions
├── app.js # JavaScript animation logic
├── png-in/ # Reveal animation frames (00000-00029)
│ ├── menu-mask_00000.png
│ ├── 1024_menu-mask_00000.png # Mobile-optimized versions
│ └── ...
└── png-out/ # Hide animation frames (00072-00101)
├── menu-mask_00072.png
├── 1024_menu-mask_00072.png # Mobile-optimized versions
└── ...
- Reveal: 30 frames (00000-00029) from
png-in/folder - Hide: 30 frames (00072-00101) from
png-out/folder - Framerate: 30fps (33ms between frames)
- Desktop: Uses full-resolution 4096x4096 PNG frames with SVG masks
- Mobile: Automatically switches to 1024x1024 versions with CSS masks
- Page loads with button disabled showing "Loading frames..."
- All PNG frames preload in background
- Button becomes active when all frames are ready
- Click button → mask animates from button center
- First click: reveal animation, second click: hide animation
- Uses inline SVG
<mask>element for stable masking - JavaScript updates the SVG
<image>href for each frame - More stable, prevents flicker during rapid frame changes
- Uses CSS
mask-imageproperty with alpha mode - Automatically detects mobile via user agent
mask-mode: alphaensures PNG transparency works correctly
Edit these constants in app.js:
const MASK_IN_DIR = 'png-in'; // Reveal frames folder
const MASK_OUT_DIR = 'png-out'; // Hide frames folder
const MASK_PREFIX = 'menu-mask_'; // Filename prefix
const IN_START = 0; // First reveal frame number
const IN_END = 29; // Last reveal frame number
const OUT_START = 72; // First hide frame number
const OUT_END = 101; // Last hide frame numberconst FRAME_INTERVAL_MS = 33; // 30fps = 33ms per frameThe system automatically uses 1024_ prefixed images on mobile. Ensure your mobile-optimized PNGs follow this naming pattern:
- Desktop:
menu-mask_00000.png - Mobile:
1024_menu-mask_00000.png
The masked content area uses CSS custom properties for positioning:
:root {
--mask-x: 50%; /* Horizontal mask position */
--mask-y: 50%; /* Vertical mask position */
--mask-w: 600px; /* Mask width */
--mask-h: 600px; /* Mask height */
}- Modern browsers: Full support with SVG masks
- Mobile Safari/Chrome: CSS mask fallback with alpha mode
- Baseline 2023: CSS
mask-modeproperty support
- Clone or download the project files
- Ensure your PNG frame sequences are in
png-in/andpng-out/folders - For mobile optimization, include
1024_prefixed versions - Open
index.htmlin a web browser - Wait for frames to load, then click the button to see the animation
- Memory Usage: Desktop ~480MB, Mobile ~30MB
- Loading Time: Depends on PNG file sizes and network speed
- GPU Optimization: Mobile uses smaller textures to prevent crashes
- Preloading: All frames loaded before any interaction to ensure smooth playback
The animation uses PNG images with alpha channels as masks:
- Alpha transparent areas: Hide the content underneath
- Alpha opaque areas: Reveal the content underneath
mask-mode: alpha: Uses PNG transparency correctly (vs luminance mode)
- SVG masks (desktop): More stable, better performance
- CSS masks (mobile): Better compatibility, prevents memory issues
- Automatic detection: Seamless switching based on user agent
This demo showcases modern web animation techniques using CSS masks, SVG, and optimized frame-based animation for a smooth user experience across all devices.