Web performance has a measured side and an experienced side.
A page can load quickly and still feel rough. A slower page can feel calm and deliberate.
We used these patterns for device mockups that load our site inside iframes.
The patterns improve the transition. They do not change the actual load time.
1. Snapshot Placeholders
The problem: A spinner left the device frame looking unfinished for one to three seconds.
The trick: Show a saved image while the live iframe loads behind it.
{/* Static placeholder; renders instantly */}
{placeholderSrc && (
<img
src={placeholderSrc}
alt=""
className="absolute inset-0 w-full h-full object-cover
transition-opacity duration-500"
style={{ opacity: iframeLoaded ? 0 : 1 }}
/>
)}
{/* Real iframe; loads in background */}
<iframe
src={url}
onLoad={() => setIframeLoaded(true)}
className="w-full h-full"
/>
The image appears first. The iframe loads without leaving an empty frame.
When the iframe loads, the image fades away.
The placeholder only needs to prevent an empty layout. It does not need to be perfect.
2. Crossfade When Ready
The problem: Hiding the device created blank space before the content appeared.
The trick: Show the placeholder immediately. Fade into the live content later.
<motion.div
initial={{ opacity: 0.9 }}
animate={{ opacity: 1 }}
transition={{ duration: 0.5 }}
>
{/* Device with placeholder already visible */}
</motion.div>
The first frame already contains useful visual content.
The live page replaces it with a quiet opacity change.
3. Use Declarative Animation
The problem: An imperative callback chain can leave a device hidden forever.
The trick: Start the animation on mount. Do not depend on iframe timing.
// Imperative (fragile):
const controls = useAnimationControls();
const handleLoad = () => controls.start({ opacity: 1 });
// If onLoad never fires... the device never appears.
// Declarative (resilient):
<motion.div
initial={{ opacity: 0.6, y: 10 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.8, delay: 0.2 }}
>
The animation runs even when the iframe is slow.
A fallback timeout can still reveal the device after eight seconds.
4. Hide Overflow at the Container
The problem: Iframes can flash a horizontal scrollbar while they settle.
The trick: Hide overflow on the container around the device group.
/* On the hero preview wrapper */
.hero-preview-container {
overflow: hidden;
}
The container catches the flash without clipping device shadows or controls.
Put the Patterns Together
-
Snapshot placeholder: show visual content at once.
-
Crossfade: move quietly into the live state.
-
Declarative animation: appear regardless of load timing.
-
Container overflow: prevent visual artifacts.
The Broader Lesson
These patterns do not make the iframe load faster.
They make each loading state look intentional.
Show something useful immediately. Upgrade it quietly. Avoid incomplete flashes.
Tags
More in Tips & Tricks
Build the Smallest Useful Slice
The smallest useful piece can help someone make progress and let the next decision come from using it.
A Smaller AI Brief Works Better
We removed repeated instructions from our AI coding setup. These practical edits leave more room for useful context.
Make it concrete
What would you like to improve?
Bring the context and the result you want. We will define the smallest useful next step.
