webdevpuneet.com

Image Reorder Grid — Drag-and-Drop Photo Order

Image Reorder Grid · Layouts · Plain HTML, CSS & JS · Live preview

CategoryLayouts

Copy & paste

Source Code

<div class="irg-card">
  <div class="irg-head">
    <h3>Product photos</h3>
    <span>Drag to reorder · first photo is the cover</span>
  </div>
  <div class="irg-grid" id="irgGrid"></div>
</div>

Extend with AI

Take This Snippet Further With AI

The AI prompt for this one is for Patreon supporters ($3 a month), along with a site with no ads. Supporters enter the passcode once and it is remembered in this browser.

· Become a supporter

What's included

Features

Native HTML5 Drag and Drop
Built on the browser's real drag events — no third-party sorting library required.
Cover position derived, not stored
Whichever photo sits at index 0 is automatically treated as the cover, so it can never drift out of sync with the actual order.
Live order numbers
Every tile shows its current position, renumbering instantly on every successful reorder.
Clear drag and drop-target feedback
The dragged tile fades and shrinks while the hovered drop target shows an inset ring, making the interaction state obvious.
Simple splice-based reorder logic
The entire reorder is two array operations (remove, then reinsert) — no complex index-shifting math to maintain.
Re-render from a single source of truth
The grid always reflects whatever order the PHOTOS array is in — no manual DOM node shuffling.
Square, responsive tiles
aspect-ratio:1 keeps every tile square regardless of grid width, ready for real photo thumbnails of any source size.
Easy to swap placeholders for real images
Each tile's color/letter placeholder is isolated to one template string, simple to replace with an <img> tag.

About this UI Snippet

Image Reorder Grid — Native Drag-and-Drop Reordering with a Live Cover Tile

Screenshot of the Image Reorder Grid snippet rendered live

Every product, gallery, or media-management UI eventually needs the same control: a grid of images a user can physically drag into a new order, with the first slot understood as "the cover" or "the primary" image. This snippet builds that exact pattern using the browser's native HTML5 Drag and Drop API — no external sorting library — with a live-updating cover badge and order numbers.

Native drag-and-drop, not a library

Every tile is a real draggable="true" element wired to the five native drag events: dragstart (marks the dragged item and records its index), dragover (calls preventDefault(), which is required for drop to fire at all, and highlights the hovered target), dragleave (clears that highlight), and drop (performs the actual reorder). This is the same API every framework-agnostic drag library wraps under the hood — using it directly here keeps the snippet dependency-free and easy to port.

The reorder itself is two array operations

On drop, PHOTOS.splice(dragIndex, 1)[0] removes the dragged photo from its old position and returns it, and PHOTOS.splice(dropIndex, 0, moved) reinserts it at the new position — the standard "remove then insert" pattern for moving an item within an array. The whole grid then re-renders from the mutated array, so the DOM never needs to be manually shuffled; it simply reflects whatever order PHOTOS is currently in.

The cover photo is a position, not a flag

Rather than storing a separate isCover: true/false field that could drift out of sync with the actual order, "being the cover" is derived purely from array position: whichever photo is at index 0 gets the .cover class, the amber ring, and the "Cover" tag, recomputed fresh on every render. Drag any other photo into the first slot and it instantly *becomes* the cover — there's no separate "set as cover" action to remember to use.

Visual feedback during the drag

The dragged tile fades to 35% opacity and shrinks slightly via .dragging, so it's visually clear which tile is in motion without it disappearing entirely (which would make it hard to track), and the tile currently being hovered over gets an inset indigo ring via .drag-over, showing exactly where the drop will land before the user releases.

Why drag-and-drop beats numbered inputs

An older pattern for photo ordering asks users to type a position number into each thumbnail — technically equivalent, but it asks people to do arithmetic about their own intent ("this should be 3rd, so the others shift down") instead of just performing the action they're thinking of. Dragging a tile to where it visually belongs maps directly to the mental model, which is why every modern photo-managing interface has converged on it over manual position fields.

Step by step

How to Use

  1. 1
    Paste HTML, CSS, and JSA 3×2 grid of six colored tiles renders, each numbered, with the first tile marked "Cover" with an amber ring and tag.
  2. 2
    Drag a tileClick and hold any tile, then drag it over another — the dragged tile fades and the hovered target shows an indigo ring.
  3. 3
    Drop to reorderRelease over the target tile — the array reorders, every tile renumbers, and the cover tag follows whichever photo is now first.
  4. 4
    Drag a different photo to the frontMove any tile into the first slot to make it the new cover — no separate "set as cover" control is needed.
  5. 5
    Replace the placeholder tiles with real imagesSwap each tile's gradient background and letter for an <img> tag, keeping the same drag event wiring.
  6. 6
    Persist the new orderAfter a drop, send the reordered PHOTOS array's ids (in order) to your backend so the new sequence and cover photo persist.

Real-world uses

Common Use Cases

E-commerce product photo management
Let sellers reorder product images and choose the cover photo shown in listings and search results.
Portfolio and gallery builders
Reorder a project's image set, with the first image used as its thumbnail elsewhere on the site.
CMS media libraries
Reorder a content block's attached images directly in an admin panel.
Social media post composers
Let users rearrange multiple photos in a post before publishing, mirroring native app carousel-editing UX.
Real estate and listing platforms
Reorder property photos with the first image controlling the listing's main thumbnail.
Learning native Drag and Drop API
A clear, dependency-free reference for the five core drag events — compare with a drag-sort list for a vertical-list variant.
Related: Splide Thumbnail Gallery
See the Splide Thumbnail Gallery for a related layouts pattern worth pairing with this one.

Got questions?

Frequently Asked Questions

Replace the gradient background and letter in each tile's template string with an <img src="..."> covering the tile (object-fit: cover), keeping the same draggable="true" attribute and the badge/cover-tag overlays positioned absolutely on top of it.

After a successful drop (inside the drop handler, after PHOTOS is reordered and render() is called), send the array of photo ids in their new order to your backend, and store which id is "first" as the designated cover image.

The native HTML5 Drag and Drop API has inconsistent mobile browser support; for mobile, add touchstart/touchmove/touchend handlers that track finger position and manually reorder on a sufficient move, or use a small touch-action-aware drag library as a progressive enhancement layer over the existing desktop drag events.

Add a small "✕" button overlay on each tile that calls PHOTOS.splice(i, 1) for that tile's index and re-renders — be sure to recompute the cover automatically afterward, since it's derived from position rather than stored.

In React, keep the photos array in useState and call setPhotos with the spliced array on drop, letting React re-render the grid; in Vue, mutate a reactive array directly with the same splice logic; in Angular, use a component array field updated via the same splice calls. The native drag event wiring is identical across frameworks since it's a browser API, not a framework feature.