Ken Burns Slideshow — Pan-Zoom Image Slider HTML CSS JS

Ken Burns Slideshow · Animations · Plain HTML, CSS & JS · Live preview

Share & Support

What's included

Features

Transform-based pan-zoom
A keyframe animates scale and translate, so the motion is GPU-smooth.
Cover-sized images
background-size: cover keeps the frame filled as the image scales.
Per-slide re-trigger
A reflow trick restarts the pan animation each time a slide becomes active.
Opacity crossfade
Stacked slides fade between each other for a soft, filmic transition.
Fading captions
Captions fade out and back in on change instead of snapping.
Hover-pause autoplay
Pauses while hovered so viewers can read, resumes on leave.
Dot nav with timer reset
Jump to any slide; manual nav resets the interval.
Photo-ready & no library
Swap gradients for img URLs; plain HTML/CSS/JS with zero dependencies.

About this UI Snippet

Ken Burns Slideshow — Slow Pan-and-Zoom Crossfading Image Slider

Screenshot of the Ken Burns Slideshow snippet rendered live

The Ken Burns effect — named for the documentary filmmaker — brings still images to life by slowly panning and zooming across them. Applied to a slideshow, it turns a static gallery into cinematic motion. This snippet builds it in plain HTML, CSS, and vanilla JavaScript: slides that drift and zoom while crossfading, with captions, dot navigation, autoplay, and hover-pause — no library.

The pan-zoom is one keyframe

Each active slide runs a @keyframes that animates its transform from a slightly zoomed, offset start to a different scale and position over several seconds — a slow drift across the image. Because it animates transform (scale and translate), it is GPU-accelerated and smooth, and the image is sized background-size: cover so it always fills the frame even as it scales. Varying both scale and translate is what gives the effect its characteristic gentle camera-move feel rather than a plain zoom.

Re-triggering the motion per slide

The subtle bit: the pan animation must restart each time a slide becomes active, or only the first slide would ever move. When showing a slide, the snippet sets animation: none, forces a reflow (void offsetWidth), then clears it — the standard reflow trick that restarts a CSS animation. So every slide gets a fresh pan as it comes in, not just on initial load.

Crossfade, not cut

Slides are stacked and transition their opacity, so the outgoing image fades as the incoming one appears — a soft crossfade rather than a hard cut. Combined with the continuing pan underneath, the transition feels filmic. The caption fades out and back in on each change so text never abruptly swaps.

Autoplay with considerate controls

It advances automatically on an interval, but pauses while the pointer is over the stage so viewers can read a caption or study an image, and resumes on leave. Dot navigation lets you jump to any slide and resets the timer so a manual pick is not immediately overridden. These touches — hover-pause, timer reset on manual nav, active-dot indicator — are what separate a polished slideshow from a bare auto-rotator.

Drop-in with real photos

The demo uses gradients so it runs with no assets, but each slide accepts an img URL — set the background to your photo and it pans across the real image. Tune the durations, the pan keyframe start/end, and the crossfade length to taste. It is a clear, dependency-free reference for the Ken Burns transform animation, CSS-animation re-triggering, and a considerate autoplay slideshow. Worth keeping in mind with real photography: because the pan keyframe both scales up and translates the image, a tightly cropped subject can drift toward the edge of frame at the animation's extremes — leaving a little extra margin around the subject when sourcing or cropping images gives the pan room to move without ever cutting off the thing the photo is actually about. will-change: transform, opacity is set on every slide for the same reason performance-sensitive carousels use it: it hints to the browser to promote the element to its own compositor layer ahead of time, so the very first frame of a pan-zoom doesn't stutter while the browser allocates that layer mid-animation.

Build with AI

Build, Understand, Optimize, and Extend It With AI

You do not have to guess why the pan animation only played once yourself. Paste this snippet's HTML, CSS, and JS into an AI coding assistant like Claude and ask it to explain exactly why setting animation to none, reading offsetWidth, then clearing the inline style is required to replay the kbPan keyframe on each new slide, or what will-change: transform, opacity is actually buying you on the compositor. The same assistant can help optimize it, for example checking whether crossfading many high-resolution background images at once causes jank on lower-end devices, or whether preloading the next slide's image ahead of time would smooth the transition. It is just as useful for extending the effect, such as varying the pan direction and duration per slide instead of using one fixed keyframe for all of them, adding swipe gestures for touch users alongside the existing dot navigation, or synchronizing the caption's entrance timing more tightly with the crossfade. Treat the code less like a finished artifact and more like a starting point for a conversation.

Prompt to recreate it

Copy this into your AI assistant of choice to build the effect from scratch, or as a jumping-off point for your own variant:

text
Build a "Ken Burns" pan-and-zoom crossfading slideshow in plain HTML, CSS, and JavaScript using only CSS transform keyframes for the motion — no canvas, no video, no animation library.

Requirements:
- A stage element containing a stack of absolutely positioned slide elements, each with its background image or gradient set to cover the frame (background-size: cover, background-position: center).
- Only the currently active slide should be visible, controlled by toggling a class that sets opacity to 1 with a CSS transition, so switching slides crossfades rather than cuts.
- The active slide must also run a CSS keyframe animation on its transform property that goes from a larger scale plus one offset to a different scale plus a different offset over several seconds, producing a slow drift-and-zoom. Mark these slide elements with will-change: transform, opacity.
- Because a CSS animation does not replay just from toggling a class if the keyframes were already assigned, when a new slide becomes active you must explicitly restart its pan animation: set its animation property to none, force a synchronous reflow by reading a layout-triggering property like offsetWidth, then clear the inline animation override so the keyframes run again from the start.
- A caption element that fades out and back in (not an abrupt swap) whenever the slide changes, plus a row of dot buttons — one per slide — where the active slide's dot is visually distinct, and clicking any dot jumps directly to that slide.
- Autoplay via setInterval that advances to the next slide on a fixed duration, but the interval must clear when the pointer enters the stage and restart when it leaves, and clicking a dot must reset the autoplay timer so the next automatic advance is not immediate.

Want to tighten it up first? Run this prompt through the AI Prompt Studio to score it across 8 quality dimensions, catch anti-patterns, and tune the wording for Claude, ChatGPT, or Gemini before you paste it in.

Step by step

How to Use

  1. 1
    Paste HTML, CSS, and JSA slideshow renders, each slide slowly panning and zooming while crossfading.
  2. 2
    Let it autoplaySlides advance on an interval; the caption and active dot update each time.
  3. 3
    Navigate manuallyClick a dot to jump to a slide; the autoplay timer resets so it is not skipped.
  4. 4
    Hover to pauseMove the pointer over the stage to pause; leave to resume.
  5. 5
    Use real photosGive each SLIDES entry an img URL — the pan-zoom plays over your image.
  6. 6
    Tune the motionAdjust the kbPan keyframe and durations for a stronger or subtler effect.

Real-world uses

Common Use Cases

Hero and banner slideshows
Cinematic motion behind a headline — pair with a video bg hero for video backdrops.
Photo galleries and portfolios
Bring still images to life, alongside a photo gallery grid.
Travel and real-estate listings
Showcase places with gentle camera movement.
Product and lookbook showcases
Pan across product photography in a hero.
Landing-page backgrounds
An animated image backdrop with overlaid content.
Learning CSS transform animation
A reference for the Ken Burns effect and animation re-triggering — compare with a carousel.

Got questions?

Frequently Asked Questions

Each active slide runs a @keyframes animation on its transform, going from a slightly larger scale with one offset to a different scale and offset over several seconds. Because it animates transform (scale + translate) rather than width/height or background-position, it is GPU-accelerated and smooth. background-size: cover keeps the image filling the frame at every scale.

A CSS animation runs once when applied; if the keyframes are already on the element, switching which slide is active will not replay them. So when a slide becomes active, the code sets animation: none, reads offsetWidth to force a reflow, then clears the inline animation — the standard trick to restart a CSS animation. Without it, only the first slide would ever pan.

Each SLIDES entry supports an img property; the code sets the slide background to url(img) when present (falling back to the gradient otherwise). Just provide image URLs (and captions), and the pan-zoom and crossfade play over your photos. Use appropriately sized images since they are scaled up slightly by the effect.

Autoplay is convenient but can advance before a viewer finishes reading a caption or looking at an image. Pausing when the pointer enters the stage (and resuming on leave) gives the viewer control without needing an explicit pause button. Manual dot navigation also resets the timer so your chosen slide is not immediately replaced by the next auto-advance.

Hold the current index in state and render slides/dots from an array. Run the autoplay interval in a useEffect (React), onMounted/onUnmounted (Vue), or ngOnInit/ngOnDestroy (Angular), clearing it on cleanup, and pause it on hover handlers. The transform keyframe and crossfade CSS are framework-agnostic; for the re-trigger, toggle a key or class so the incoming slide remounts/replays.