Crossfade
Also called cross-fade or cross dissolve
A transition where the old content fades out while the new content fades in at the same spot, so the two briefly overlap.
import { useState } from 'react';
const photos = [
{ src: '/photos/lake.jpg', alt: 'Morning fog over a mountain lake' },
{ src: '/photos/dunes.jpg', alt: 'Sand dunes at sunset' },
{ src: '/photos/forest.jpg', alt: 'Sunlight through a pine forest' }
];
export function PhotoViewer() {
const [active, setActive] = useState(0);
return (
<div className='w-96'>
{/* Every photo sits in the same grid cell, so the old and new one overlap while they fade. */}
<div className='grid aspect-4/3 overflow-hidden rounded-2xl bg-muted'>
{photos.map((photo, index) => (
<img
key={photo.src}
src={photo.src}
alt={photo.alt}
aria-hidden={index !== active}
className={`col-start-1 row-start-1 size-full object-cover transition-opacity duration-300 ease-in-out ${index === active ? 'opacity-100' : 'opacity-0'}`}
/>
))}
</div>
<div className='mt-3 flex gap-2'>
{photos.map((photo, index) => (
<button
key={photo.src}
type='button'
aria-label={photo.alt}
aria-pressed={index === active}
onClick={() => setActive(index)}
className='overflow-hidden rounded-lg opacity-60 transition-opacity aria-pressed:opacity-100 aria-pressed:ring-2 aria-pressed:ring-ring'
>
<img src={photo.src} alt='' className='size-14 object-cover' />
</button>
))}
</div>
</div>
);
}When the selected photo changes, crossfade from the old image to the new one: stack both in the same spot and animate opacity over 300ms with ease-in-out, fading the new image in while the old one fades out, with no blank frame in between. Keep the image container at a fixed aspect ratio so nothing shifts during the fade.
Paste into Layerwise or any AI coding tool.
What is Crossfade?
A crossfade swaps one thing for another in place. Both versions sit on top of each other and their opacity changes at the same time: the old one goes from 1 to 0 while the new one goes from 0 to 1. There is never an empty moment, so the change feels calm and quick.
Use it when content changes but its position stays the same: a new photo in a gallery, an icon switching from play to pause, a tab panel, a label that updates. If the content also moves or resizes, pair the crossfade with a layout animation or use a morph.
A common mistake is fading the old content out completely before fading the new one in. That leaves a blank flash in the middle and makes the change feel slower. Stack both versions in the same spot, for example in a single CSS Grid cell or with absolute positioning, so they can overlap. Keep it short: 150 to 300ms for small UI and up to 500ms for large images.
Often confused with
- Fade in
- A fade-in brings one element onto the screen. A crossfade replaces one element with another by fading both at once.
Related terms
All termsFade in
An entrance animation where an element goes from fully transparent to fully visible, so it appears gently instead of popping in.
Morph
A transition where one shape smoothly changes its size, corners, and contents into another, like a small pill growing into a full card.
View Transitions API
A browser feature that animates between two states of a page by snapshotting the old view, applying your update, and animating to the new one.
Enter and exit animations
The pair of animations an element plays as it is added to the page and as it is removed, so changes to a list or layout are easy to follow.
Build it with Layerwise
Describe your app, watch it run in a live preview, and publish it with a database, storage, and sign-in built in.

