Source Code

<div class="container py-5 d-flex justify-content-center">
  <div class="card bsdrag-card">
    <div class="card-body p-3">
      <h6 class="fw-bold mb-2">Priority order</h6>
      <ul class="list-unstyled mb-0" id="bsdragList"></ul>
      <p class="small text-muted mt-2 mb-0">Drag the handle to reorder.</p>
    </div>
  </div>
</div>

Bootstrap Drag-to-Reorder List — Free HTML CSS JS Snippet

Bootstrap Drag-to-Reorder List · Forms · Plain HTML, CSS & JS · Live preview

What's included

Features

Uses the genuine native HTML5 Drag and Drop API, not a custom pointer-events reimplementation
Reordering is a real array splice-out/splice-in, not a purely visual DOM shuffle disconnected from the data
Rank numbers are rendered from the array's live order, always accurate after every reorder
A clear visual drop-target indicator shows exactly where an item would land before releasing
Dropping an item onto its own current position is correctly treated as a no-op

About this UI Snippet

Bootstrap Drag-to-Reorder List — HTML, CSS & JavaScript

Screenshot of the Bootstrap Drag-to-Reorder List snippet rendered live

This uses the browser's actual native HTML5 Drag and Drop API — draggable="true" on each row plus dragstart/dragover/drop listeners — rather than a pointer-events-based reimplementation, the same approach this collection's bootstrap-kanban-board-cards uses for moving cards between columns, applied here to reordering within a single list instead.

The one line that's easy to leave out and silently breaks everything is e.preventDefault() inside the dragover handler — without it, the browser's default behavior refuses the drop entirely, and the drop event never fires on the element at all, no matter how correct the rest of the drop logic is.

The actual reordering is a genuine array move, not a DOM-only shuffle: items.splice(fromIndex, 1) removes the dragged item from its old position, and items.splice(toIndex, 0, moved) reinserts it at the new one, then render() rebuilds the whole list from that updated array — including the visible rank number next to each row, which is what makes the numbers 1 through 4 always correctly reflect the list's true current order rather than needing separate logic to keep them in sync with whatever the drag-and-drop just did visually.

Build with AI

Build, Understand, Optimize, and Extend It With AI

Hand this snippet to an AI coding assistant like Claude and ask it to add touch-friendly reordering (e.g. via Pointer Events, since native HTML5 drag-and-drop is unreliable on mobile) as a fallback for touch devices, or to add keyboard-accessible reordering (e.g. Alt+ArrowUp/ArrowDown to move the focused item) as an alternative to mouse-only dragging.

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 Bootstrap 5.3 drag-to-reorder list, using the real Bootstrap CDN framework (bootstrap.min.css and bootstrap.bundle.min.js) for the surrounding card, and the browser's native HTML5 Drag and Drop API for the actual reordering — not a custom pointer-events reimplementation.

Requirements:
- A list of at least 4 items, each with draggable="true", a visible drag handle, and a rank number showing its current position.
- Implement dragstart (marking the dragged row and storing its id), dragover (calling preventDefault so the drop is actually accepted, and showing a visual indicator on the row currently being hovered over), dragend (clearing all drag-related visual state), and drop (performing the actual reorder).
- The reorder itself must be a real array operation — remove the dragged item from its old index and reinsert it at the dropped-on item's index — followed by a full re-render of the list from that updated array, so the rank numbers shown always reflect the array's true current order.
- Dropping an item onto its own current position must be a no-op with no visible change.

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
    Load the snippetFour priority items list in order, each numbered 1 through 4 with a drag handle icon.
  2. 2
    Press and drag the handle on item 3It fades to semi-transparent while dragging, and rows show a blue top border as you hover over a valid drop target.
  3. 3
    Drop it above item 1The list reorders immediately, and every row's rank number updates to reflect the new true order.
  4. 4
    Drag item 1 (now originally item 3) down to the bottomIt moves correctly, and the numbering stays accurate throughout.
  5. 5
    Try dropping an item onto itselfNothing changes — dropping a row where it already is is correctly treated as a no-op.

Real-world uses

Common Use Cases

Priority lists, to-do ordering, and custom sort preferences
Pairs with bootstrap-todo-list-app for a fully reorderable task list.
Dashboard widget or navigation menu ordering
Let a user customize the order of items in a settings or layout-configuration screen.
Playlist, queue, and step-ordering interfaces
Any list where the sequence itself carries meaning benefits from a direct drag-to-reorder interaction.

Got questions?

Frequently Asked Questions

Browsers refuse a drop by default unless something explicitly opts in during dragover — omitting that one call means the drop event never fires at all on that element, regardless of how correct the rest of the drop-handling logic is.

Yes — the reorder is a real Array.splice() operation on the items array itself, and render() rebuilds the entire list (including the rank numbers) from that array afterward, so the visible order is never just a disconnected DOM rearrangement.

The native HTML5 Drag and Drop API has inconsistent and often poor support on mobile touch browsers; a production implementation targeting mobile should use a pointer-events-based drag library or fallback instead of relying on this API alone.

Yes. Keep items as an array in component state, and perform the same splice-based reorder inside your drop handler, updating state immutably (a new array, not a mutated one) per your framework's conventions.