Screenshot stack
Two or three screenshots overlapping in a static composition.
npx shadcn@latest add https://ui.goodtabs.co/r/screenshot-stack.json
With the @goodtabs namespace in components.json: npx shadcn@latest add @goodtabs/screenshot-stack



Three screenshots stepping down and to the right.
Two layers


A front and a back screenshot.
Usage
import { ScreenshotStack } from "@/components/ui/screenshot-stack"
<ScreenshotStack shots={[
{ src: "/a.jpg", alt: "Dashboard" },
{ src: "/b.jpg", alt: "Settings" },
]} />Props
| Prop | Type | Default | Description |
|---|---|---|---|
| shots | [Shot, Shot] | [Shot, Shot, Shot] | Two or three { src, alt } items, back to front. The last is on top. | |
| maxWidth | string | Constrain the stack, for example "420px". |
Source
screenshot-stack/screenshot-stack.tsx
import * as React from "react";
import { cn } from "@/lib/utils";
type Shot = { src: string; alt: string };
type ScreenshotStackProps = Omit<React.ComponentProps<"div">, "children"> & {
/** Two or three screenshots, back to front. The last one is on top. */
shots: [Shot, Shot] | [Shot, Shot, Shot];
/** Constrain the stack, for example "420px". */
maxWidth?: string;
};
// Each layer steps 12% right and 10% down, shrinking nothing, so the frames overlap by the same amount.
const offsets = ["left-0 top-0", "left-[12%] top-[10%]", "left-[24%] top-[20%]"] as const;
/** A static composition of overlapping screenshots, each in a bordered frame. */
export function ScreenshotStack({ shots, maxWidth, className, style, ...props }: ScreenshotStackProps) {
return (
<div
className={cn("relative aspect-[4/3] w-full", className)}
style={{ maxWidth, ...style }}
{...props}
>
{shots.map((shot, index) => (
// eslint-disable-next-line @next/next/no-img-element
<img
key={shot.src}
src={shot.src}
alt={shot.alt}
loading="lazy"
className={cn(
"absolute aspect-3/2 w-[68%] rounded-lg border bg-background object-cover shadow-sm",
offsets[index],
)}
style={{ zIndex: index }}
/>
))}
</div>
);
}
For AI agents
Hand your agent this page, the markdown at /components/screenshot-stack/prompt.md, or the Copy AI prompt button above.
When to use
- Showing several screens of a product in one hero image
- Beside a headline where one screenshot feels thin
When not to use
- Screenshots people need to read; the layers hide part of each
- More than three images, which want a grid
Agent notes
- Server component with no motion; positions are percentages, so it scales with its width
- Each layer is 68% wide, offset 12% right and 10% down from the one behind
- The stack has a 4 by 3 box and layers keep a 3 by 2 ratio