Create and Reorder Lists With Drag-and-Drop | SortableJS

Sortable is a JavaScript library for reorderable drag-and-drop menus and a library that makes the list of items sortable/reorderable using the native Html5 API for drag-and-drop. Works with all modern browsers and touch devices.


  • Supports touch devices and modern browsers (including IE9)
  • Can drag from one list to another or within the same list
  • CSS animation when moving items
  • Supports drag handles and selectable text (better than voidberg’s html5sortable)
  • Smart auto-scrolling
  • Advanced swap detection
  • Smooth animations
  • Multi-drag support
  • Support for CSS transforms
  • Built using native HTML5 drag-and-drop API
  • Supports
    • Meteor
    • Angular
      • 2.0+
      • 1.*
    • React
      • ES2015+
      • Mixin
    • Knockout
    • Polymer
    • Vue
    • Ember
  • Supports any CSS library, e.g. Bootstrap
  • Simple API
  • Support for plugins
  • CDN
  • No jQuery is required (but there is support)
  • Typescript definitions at @types/sortablejs

Must Read: A Simple Drag-and-drop Hierarchical List For A Vue Component

How to make use of it:


$ npm install sortablejs --save

1. Import the SortableJS.

import Sortable from 'sortablejs';

// or
<script src="Sortable.min.js"></script>

2. Create a listing of draggable objects on the web page.

<ul id="example">
  <li>Item 1</li>
  <li>Item 2</li>
  <li>Item 3</li>
  <li>Item 4</li>
  <li>Item 5</li>
  <li>Item 6</li>
  <li>Item 7</li>
  <li>Item 8</li>

3. Enable the Draggable & Sortable performance on the listing.

new Sortable(document.getElementById('example'), {
    // options here

4. All attainable choices with default values.

new Sortable(el, {

    // name: String — group name
    // pull: true|false|["foo", "bar"]|'clone'|function — ability to move from the list. clone — copy the item, rather than move. Or an array of group names which the elements may be put in. Defaults to true.
    // put: true|false|["baz", "qux"]|function — whether elements can be added from other lists, or an array of group names from which elements can be added.
    // revertClone: boolean — revert cloned element to initial position after moving to a another list.
    group: "name",  // or { name: "...", pull: [true, false, 'clone', array], put: [true, false, array] }

    // enable sorting
    sort: true,  

    // time to wait before the sorting should start
    delay: 0

    // enable delay on touch
    delayOnTouchOnly: false,

    // how many pixels the point should move before cancelling a delayed drag event
    touchStartThreshold: 0, 

    // disables the sortable if set to true.
    disabled: false, 

    // which items inside the element should be draggable
    draggable: '>*'

    // save and restore the sort.
    store: null,

    // animation speed
    animation: 0,

    // easing function: "cubic-bezier(1, 0, 0, 1)"
    easing: null, 

    // drag handle
    handle: ".my-handle",

    // elements to ignore
    ignore: 'a, img',

    // filter selector
    filter: ".ignore-elements", 

    // preverntDefault when filtering
    preventOnFilter: true,

    // drop placeholder
    ghostClass: "sortable-ghost",

    // chosen class
    chosenClass: "sortable-chosen",

    // dragging class
    dragClass: "sortable-drag",

    // default data attribute
    dataIdAttr: 'data-id',

    // enable drop bubble
    dropBubble: false,

    // threshold of the swap zone
    swapThreshold: 1,

    // invert swap
    invertSwap: false,

    // threshold of the inverted swap zone
    invertedSwapThreshold: 1,

    // will be detected automatically if not given
    direction: 'horizontal',

    // ignore the HTML5 DnD behaviour
    forceFallback: false,

    // fallback class
    fallbackClass: "sortable-fallback",

    // appends the cloned DOM Element into the document body
    fallbackOnBody: false,  

    // how far the mouse should move before it's considered as a drag.
    fallbackTolerance: 0, 

    // fallback offsets
    fallbackOffset: {
        x: 0,
        y: 0

    dragoverBubble: false,

    // remove the cloned element when it is not showing
    removeCloneOnHide: true, 

    // distance mouse must be from empty sortable to insert drag element into it
    emptyInsertThreshold: 5, // px, 

    // set data
    setData: function (/** DataTransfer */dataTransfer, /** HTMLElement*/dragEl) {
      dataTransfer.setData('Text', dragEl.textContent); // `dataTransfer` object of HTML5 DragEvent

    // scroll plugin options

    // Enable the plugin. Can be HTMLElement.
    scroll: true, 

    // if you have custom scrollbar scrollFn may be used for autoscrolling
    scrollFn: function(offsetX, offsetY, originalEvent, touchEvt, hoverTargetEl) { ... }, 

    // px, how near the mouse must be to an edge to start scrolling.
    scrollSensitivity: 30, 

    // px, speed of the scrolling
    scrollSpeed: 10, 

    // apply autoscroll to all parent elements, allowing for easier movement
    bubbleScroll: true,

    // OnSpill Plugin options

    // Enable plugin
    revertOnSpill: true, 
    // Called when item is spilled
    onSpill: function(/**Event*/evt) {
      evt.item // The spilled item

    // MultiDrag Plugin options

    // Enable the plugin
    multiDrag: true, 

    // Class name for selected item
    selectedClass: "sortable-selected", 

    // Key that must be down for items to be selected
    multiDragKey: null, 

    // Called when an item is selected
    onSelect: function(/**Event*/evt) {
      evt.item // The selected item

    // Called when an item is deselected
    onDeselect: function(/**Event*/evt) {
      evt.item // The deselected item

    // Swap Plugin options

    // Enable swap mode
    swap: true, 

    // Class name for swap item (if swap mode is enabled)
    swapClass: "sortable-swap-highlight",

5. Callback features.

new Sortable(el, {

    // Element is chosen
    onChoose: function (/**Event*/evt) {
      evt.oldIndex;  // element index within parent

    // Element is unchosen
    onUnchoose: function(/**Event*/evt) {
      // same properties as onEnd

    // Element dragging started
    onStart: function (/**Event*/evt) {
      evt.oldIndex;  // element index within parent

    // Element dragging ended
    onEnd: function (/**Event*/evt) {
      var itemEl = evt.item;  // dragged HTMLElement;    // target list
      evt.from;  // previous list
      evt.oldIndex;  // element's old index within old parent
      evt.newIndex;  // element's new index within new parent
      evt.clone // the clone element
      evt.pullMode;  // when item is in another sortable: `"clone"` if cloning, `true` if moving

    // Element is dropped into the list from another list
    onAdd: function (/**Event*/evt) {
      // same properties as onEnd

    // Changed sorting within list
    onUpdate: function (/**Event*/evt) {
      // same properties as onEnd

    // Called by any change to the list (add / update / remove)
    onSort: function (/**Event*/evt) {
      // same properties as onEnd

    // Element is removed from the list into another list
    onRemove: function (/**Event*/evt) {
      // same properties as onEnd

    // Attempt to drag a filtered element
    onFilter: function (/**Event*/evt) {
      var itemEl = evt.item;  // HTMLElement receiving the `mousedown|tapstart` event.

    // Event when you move an item in the list or between lists
    onMove: function (/**Event*/evt, /**Event*/originalEvent) {
      // Example:,output
      evt.dragged; // dragged HTMLElement
      evt.draggedRect; // DOMRect {left, top, right, bottom}
      evt.related; // HTMLElement on which have guided
      evt.relatedRect; // DOMRect
      evt.willInsertAfter; // Boolean that is true if Sortable will insert drag element after target by default
      originalEvent.clientY; // mouse position
      // return false; — for cancel
      // return -1; — insert before target
      // return 1; — insert after target

    // Called when creating a clone of element
    onClone: function (/**Event*/evt) {
      var origEl = evt.item;
      var cloneEl = evt.clone;

    // Called when dragging element changes position
    onChange: function(/**Event*/evt) {
      evt.newIndex // most likely why this event is used is to get the dragging element's current index
      // same properties as onEnd


Static methods & properties

Sortable.create(el:HTMLElement[, options:Object]):Sortable

Create a new instance.

Must Read: Advanced Vue Drag-and-drop Component-Based On Sortable.js

The active Sortable instance.


The element being dragged.


The ghost element.


The clone element.


Get the Sortable instance on an element.


Mounts a plugin to Sortable.

See Also –

Enable HTML5-Based Drag-and-Drop Functionality In The List of Items | jQuery DragNDrop
Multi-Browser, Mobile-Compatible Drag-and-Drop JavaScript Library | Drog.js
Responsive Drag-and-Drop, Multi-Column Grid Layout | gridstack.js

See Demo And Download

Official Website(SortableJS): Click Here

This superior jQuery/javascript plugin is developed by SortableJS. For extra Advanced usage, please go to the official website.

Related Posts


Confetti Falling Animation Effect In JavaScript | party.js

Party.js is a JavaScript library to brighten user site experience with visual effects! Celebrate success with dom confetti! The library is written in TypeScript and compiled into…


Simple jQuery Cookie Consent Plugin

jquery.cookie-consent is a simple jQuery plugin to request consent to use cookies. An easy-to-use and highly customizable cookie consent bar that informs your visitors of the use…


Timepicker JavaScript Plugin for jQuery Inspired by Google Calendar

jquery.timepicker is a lightweight jQuery timer plugin inspired by Google Calendar. It supports both mouse and keyboard navigation and weighs 5.5KB minified and compact. Features: Highly customizable…


A Lightweight, Touchable, and Responsive Angular Universal Carousel Library

ngxCarousel is a lightweight, tactile, and responsive library for creating an angular carousel. No dependencies, no more hammer. Must Read: Angular Responsive Image Slider With Lightbox Popup…


First Mobile Full-screen Modal Popup Library For Vue

Vue full-page modal is a responsive, mobile-compatible, screen-friendly pop-up library for Vue.js. Must Read: Modal Component Is Written in Vanilla JS | ensemble Modal How to make…


Generate a Random Number Picker In Vanilla JavaScript

Random Number Picker is a Vanilla JS-based number picker that allows you to generate a random number within a specified range. Must Read: Generating Lottery Numbers Using…