Making thousands of DOM elements draggable with JavaScript This is a very simple implementation of dragging elements in html/js. I'm working on a web application that could have thousands of draggable elements on screen at any given time.

Currently, this code works perfectly as shown below (with only one draggable element), however if I copy and paste that element (&lt;span class="draggable"&gt;This is draggable&lt;/span&gt;) a few thousand times (I've been using around 4000 for testing) page load is significantly slower, and the framerate slows considerably. 

I can understand the page load slowing due to the number of elements, but is there anything that can be done to ensure the frame rate remains smooth while dragging an element given large numbers of draggable elements in the DOM?

Note - The implementation here deliberately ignores various issues like scrolling and so on that I will be implementing later, and I believe will have a largely negligible effect on performance. If that's an incorrect assumption please let me know.

dragdrop.html

&lt;!doctype html&gt;
&lt;html&gt;
    &lt;head&gt;
        &lt;title&gt;Drag + Drop&lt;/title&gt;
        &lt;link rel="stylesheet" type="text/css" href="dragdrop.css" /&gt;
    &lt;/head&gt;
    &lt;body&gt;
        &lt;div id="draggableItemContainer" class="noselect"&gt;
            &lt;span class="draggable"&gt;This is draggable&lt;/span&gt;
        &lt;/div&gt;
        &lt;script src="https://code.jquery.com/jquery-1.12.4.min.js"&gt;&lt;/script&gt;
        &lt;script type="text/javascript" src="dragdrop.js"&gt;&lt;/script&gt;
    &lt;/body&gt;
&lt;/html&gt;


dragdrop.css

span {
    position:absolute;
    background: #FF8888;
    cursor: pointer;
}

.noselect {
    -webkit-touch-callout: none;
    -webkit-user-select: none;
    -khtml-user-select: none;
    -moz-user-select: none;
    -ms-user-select: none;
    user-select: none;
}


dragdrop.js

var dragDrop = (function() {
    var elementBeingDragged;
    var clickPointOffsetX;
    var clickPointOffsetY;

    function _dragging(e) {
        elementBeingDragged.style.left = (e.clientX - clickPointOffsetX) + "px";
        elementBeingDragged.style.top = (e.clientY - clickPointOffsetY) + "px";
    }

    function _stopDrag(e) {
        document.removeEventListener('mousemove', _dragging);
        document.removeEventListener('mouseup', _stopDrag);
    }

    function startDrag(e) {
        elementBeingDragged = this;
        document.addEventListener('mouseup', _stopDrag);
        document.addEventListener('mousemove', _dragging);

        var rect = elementBeingDragged.getBoundingClientRect();

        clickPointOffsetX = e.clientX - rect.left;
        clickPointOffsetY = e.clientY - rect.top;
    }

    var publicAPI = {
        startDrag: startDrag
    };

    return publicAPI;
})();

$(function() {
    $('#draggableItemContainer').on('mousedown', '.draggable', dragDrop.startDrag);
});
Here are some suggestions to improve the fluidity of your app:

Use translate instead of top/left positioning

According to this blog post: https://www.paulirish.com/2012/why-moving-elements-with-translate-is-better-than-posabs-topleft/, translate is much more efficient regarding the CPU usage

Use requestAnimationFrame

https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame

This function allows you to do the computation only if required (see this SO answer on how to combine it with mousemove: https://stackoverflow.com/a/23658815/3207406)