2.15 · Animation

Hover Image Preview.

A list of links. Hover any one — a preview image follows your cursor. The signature interaction on portfolio + agency sites.

What it is

An index of projects, articles, or case studies. Each entry is text-only: number, title, year. When you hover one, a project thumbnail appears and tracks your cursor. The result is a clean, almost editorial table of contents — no images visible until you ask for them. Used by countless agency and portfolio sites because it scales beautifully: 50 projects can sit in one screen, but each gets a rich visual on demand.

How it works

A single floating div sits at the parent's position: relative, absolutely-positioned, hidden by default. Each link in the list gets a data-preview attribute pointing to which image to show. On mouseenter of a link, set the right image as active and add a class to show the preview. On mousemove over the parent, update the preview's transform: translate(x, y) to follow the cursor (use a small lerp for smoothness). On mouseleave, hide.

Single floating previewOne absolutely-positioned div, NOT one per link
data-preview attributeEach link points to which image variant to show
mousemove follows cursorUpdate transform on mousemove with lerp for smooth tracking
Disable on touch@media (hover: none) display:none — no cursor on mobile

Live demo

Hover any project — a colored preview pops in and follows your cursor.

Live · hover
— Selected work · 2018 → 2026
Aurora

Copy this prompt

Prompt · 2.15 Hover Image Preview
Build a project-index list with hover image previews. Parent container position:relative. List items are large text-only rows: number column, big display-serif title, year — separated by hairline borders. On hover, the title color changes to accent and slides 6px right (transform:translateX). Each row has a data-preview="N" attribute matching one of several preview images. ONE absolutely-positioned preview div sits in the parent: 280px wide, 3/4 aspect, border-radius:14px, overflow:hidden, with all preview images stacked inside (only one with .on opacity:1 at a time). Default opacity:0, transform:translate(-50%,-50%) scale(0.85). On row mouseenter, swap which preview .art has .on and add .show class. On mousemove inside the parent, update the preview's transform to translate(cursorX, cursorY) with a lerp for smooth following. On row mouseleave, remove .show. Hide entirely on touch devices via @media (hover: none).

Example sites to study