# Create a Draggable Element in JavaScript

**URL:** https://forum.kirupa.com/t/create-a-draggable-element-in-javascript/638149
**Category:** programming
**Created:** [April 28, 2018, 5:27am UTC](https://forum.kirupa.com/t/create-a-draggable-element-in-javascript/638149 "2018-04-28T05:27:37Z")
**Posts on this page:** 20
**Page:** 1

<div class="post-metadata">

### Author: ![kirupa](https://yyz1.discourse-cdn.com/flex011/user_avatar/forum.kirupa.com/kirupa/32/11616_2.png) [@kirupa](https://forum.kirupa.com/u/kirupa)
#### Post date: [April 28, 2018, 5:27am UTC](https://forum.kirupa.com/t/create-a-draggable-element-in-javascript/638149/1 "2018-04-28T05:27:38Z")

</div>

by [kirupa](http://www.kirupa.com/www.kirupa.com/about/whatiskirupa.htm) | 26 April 2018

[Have questions? Discuss this HTML5 / JavaScript tutorial with others on the forums.](http://www.kirupa.com/www.kirupa.com/forum/showthread.php?370334-Tutorial-Random-Numbers-in-JavaScript)

* * *
This is a companion discussion topic for the original entry at [http://www.kirupa.com/html5/drag.htm](http://www.kirupa.com/html5/drag.htm)

---

<div class="post-metadata">

### Author: ![Alvin\_Tan\_Hoe\_Leong](https://yyz1.discourse-cdn.com/flex011/user_avatar/forum.kirupa.com/alvin_tan_hoe_leong/32/9224_2.png) [@Alvin\_Tan\_Hoe\_Leong](https://forum.kirupa.com/u/Alvin_Tan_Hoe_Leong)
#### Post date: [July 30, 2018, 1:45pm UTC](https://forum.kirupa.com/t/create-a-draggable-element-in-javascript/638149/2 "2018-07-30T13:45:15Z")

</div>

Hi,  
How about if i want to have multiple draggable elements?  
Thank you very much for your concerning.

---

<div class="post-metadata">

### Author: ![kirupa](https://yyz1.discourse-cdn.com/flex011/user_avatar/forum.kirupa.com/kirupa/32/11616_2.png) [@kirupa](https://forum.kirupa.com/u/kirupa)
#### Post date: [July 31, 2018, 3:58am UTC](https://forum.kirupa.com/t/create-a-draggable-element-in-javascript/638149/3 "2018-07-31T03:58:30Z")

</div>

Hi Alvin!  
That will require adjusting the draggable element from being [hard coded for a single element](https://www.kirupa.com/html5/drag.htm) to handle an arbitrary number of elements. I used the ideas from the [Handling Events for Many Elements](https://www.kirupa.com/html5/handling_events_for_many_elements.htm) article to make that adjustment.

The full code for being able to drag multiple elements looks as follows:

```
<!DOCTYPE html>
<html>

<head>
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no" />
  <title>Drag Multiple Elements</title>
  <style>
    #container {
      width: 100%;
      height: 400px;
      background-color: #333;
      display: flex;
      align-items: center;
      justify-content: center;
      overflow: hidden;
      border-radius: 7px;
      touch-action: none;
    }

    .item {
      border-radius: 50%;
      touch-action: none;
      user-select: none;
      position: relative;
    }

    .one {
      width: 100px;
      height: 100px;
      background-color: rgb(245, 230, 99);
      border: 10px solid rgba(136, 136, 136, .5);
      top: 0px;
      left: 0px;
    }

    .two {
      width: 60px;
      height: 60px;
      background-color: rgba(196, 241, 190, 1);
      border: 10px solid rgba(136, 136, 136, .5);
      top: 30%;
      left: 10%;
    }

    .three {
      width: 40px;
      height: 40px;
      background-color: rgb(0, 255, 231);
      border: 10px solid rgba(136, 136, 136, .5);
      top: -40%;
      left: -10%;
    }

    .four {
      width: 80px;
      height: 80px;
      background-color: rgb(233, 210, 244);
      border: 10px solid rgba(136, 136, 136, .5);
      top: -10%;
      left: 5%;
    }

    .item:active {
      opacity: .75;
    }

    .item:hover {
      cursor: pointer;
    }
  </style>
</head>

<body>

  <div id="outerContainer">
    <div id="container">
      <div class="item one">

      </div>
      <div class="item two">

      </div>
      <div class="item three">

      </div>
      <div class="item four">

      </div>
    </div>
  </div>

  <script>
    var container = document.querySelector("#container");
    var activeItem = null;

    var active = false;

    container.addEventListener("touchstart", dragStart, false);
    container.addEventListener("touchend", dragEnd, false);
    container.addEventListener("touchmove", drag, false);

    container.addEventListener("mousedown", dragStart, false);
    container.addEventListener("mouseup", dragEnd, false);
    container.addEventListener("mousemove", drag, false);

    function dragStart(e) {

      if (e.target !== e.currentTarget) {
        active = true;

        // this is the item we are interacting with
        activeItem = e.target;

        if (activeItem !== null) {
          if (!activeItem.xOffset) {
            activeItem.xOffset = 0;
          }

          if (!activeItem.yOffset) {
            activeItem.yOffset = 0;
          }

          if (e.type === "touchstart") {
            activeItem.initialX = e.touches[0].clientX - activeItem.xOffset;
            activeItem.initialY = e.touches[0].clientY - activeItem.yOffset;
          } else {
            console.log("doing something!");
            activeItem.initialX = e.clientX - activeItem.xOffset;
            activeItem.initialY = e.clientY - activeItem.yOffset;
          }
        }
      }
    }

    function dragEnd(e) {
      if (activeItem !== null) {
        activeItem.initialX = activeItem.currentX;
        activeItem.initialY = activeItem.currentY;
      }

      active = false;
      activeItem = null;
    }

    function drag(e) {
      if (active) {
        if (e.type === "touchmove") {
          e.preventDefault();

          activeItem.currentX = e.touches[0].clientX - activeItem.initialX;
          activeItem.currentY = e.touches[0].clientY - activeItem.initialY;
        } else {
          activeItem.currentX = e.clientX - activeItem.initialX;
          activeItem.currentY = e.clientY - activeItem.initialY;
        }

        activeItem.xOffset = activeItem.currentX;
        activeItem.yOffset = activeItem.currentY;

        setTranslate(activeItem.currentX, activeItem.currentY, activeItem);
      }
    }

    function setTranslate(xPos, yPos, el) {
      el.style.transform = "translate3d(" + xPos + "px, " + yPos + "px, 0)";
    }
  </script>
</body>

</html>

```

You can see a live demo of it here: [https://www.kirupa.com/html5/examples/drag\_multiple.htm](https://www.kirupa.com/html5/examples/drag_multiple.htm)

Let me know if this works for you.

Cheers,  
Kirupa

---

<div class="post-metadata">

### Author: ![Alvin\_Tan\_Hoe\_Leong](https://yyz1.discourse-cdn.com/flex011/user_avatar/forum.kirupa.com/alvin_tan_hoe_leong/32/9224_2.png) [@Alvin\_Tan\_Hoe\_Leong](https://forum.kirupa.com/u/Alvin_Tan_Hoe_Leong)
#### Post date: [July 31, 2018, 10:45am UTC](https://forum.kirupa.com/t/create-a-draggable-element-in-javascript/638149/4 "2018-07-31T10:45:42Z")

</div>

Hi Kirupa,

Yes, it works pretty well.  
This code really helps me a lot.  
Thank you very much.

Best Regards,  
Alvin

---

<div class="post-metadata">

### Author: ![Joe\_Bloggs](https://avatars.discourse-cdn.com/v4/letter/j/e99b99/32.png) [@Joe\_Bloggs](https://forum.kirupa.com/u/Joe_Bloggs)
#### Post date: [August 27, 2018, 4:44am UTC](https://forum.kirupa.com/t/create-a-draggable-element-in-javascript/638149/5 "2018-08-27T04:44:13Z")

</div>

Quick note, you’ll want to move preventDefault out of the if statement or you will have problems…

```auto
if (e.type === "touchmove") {
          e.preventDefault();
          
          currentX = e.touches[0].clientX - initialX;
          currentY = e.touches[0].clientY - initialY;
        } else {
          currentX = e.clientX - initialX;
          currentY = e.clientY - initialY;
        }

```

Should be:

```auto
e.preventDefault();
if(e.type === "touchmove"){ ...

```

---

<div class="post-metadata">

### Author: ![kirupa](https://yyz1.discourse-cdn.com/flex011/user_avatar/forum.kirupa.com/kirupa/32/11616_2.png) [@kirupa](https://forum.kirupa.com/u/kirupa)
#### Post date: [August 27, 2018, 6:13am UTC](https://forum.kirupa.com/t/create-a-draggable-element-in-javascript/638149/6 "2018-08-27T06:13:43Z")

</div>

@Joe_Bloggs - What are the problems? I tested it on my iPhone with the code as-is, and I’m able to drag the element around ☹ 🙂

---

<div class="post-metadata">

### Author: ![Joe\_Bloggs](https://avatars.discourse-cdn.com/v4/letter/j/e99b99/32.png) [@Joe\_Bloggs](https://forum.kirupa.com/u/Joe_Bloggs)
#### Post date: [August 27, 2018, 3:24pm UTC](https://forum.kirupa.com/t/create-a-draggable-element-in-javascript/638149/7 "2018-08-27T15:24:54Z")

</div>

The code is great! But you only have preventDefault for mobile, not for laptops or desktop browsers, so it will not work unless you move preventDefault() out of the “if” block of code it is currently in (where it is only testing for mobile devices)

---

<div class="post-metadata">

### Author: ![kirupa](https://yyz1.discourse-cdn.com/flex011/user_avatar/forum.kirupa.com/kirupa/32/11616_2.png) [@kirupa](https://forum.kirupa.com/u/kirupa)
#### Post date: [August 27, 2018, 6:07pm UTC](https://forum.kirupa.com/t/create-a-draggable-element-in-javascript/638149/8 "2018-08-27T18:07:44Z")

</div>

That is a great point. I’ll update the code momentarily 🙂

---

<div class="post-metadata">

### Author: ![brucenorton](https://yyz1.discourse-cdn.com/flex011/user_avatar/forum.kirupa.com/brucenorton/32/9288_2.png) [@brucenorton](https://forum.kirupa.com/u/brucenorton)
#### Post date: [September 18, 2018, 4:24pm UTC](https://forum.kirupa.com/t/create-a-draggable-element-in-javascript/638149/9 "2018-09-18T16:24:57Z")

</div>

Thanks for this. Works very well.  
Do you have something that would detect collisions on dragEnd?  
I am trying to only allow “dropping” if dropped in the proper place.

---

<div class="post-metadata">

### Author: ![kirupa](https://yyz1.discourse-cdn.com/flex011/user_avatar/forum.kirupa.com/kirupa/32/11616_2.png) [@kirupa](https://forum.kirupa.com/u/kirupa)
#### Post date: [September 18, 2018, 9:15pm UTC](https://forum.kirupa.com/t/create-a-draggable-element-in-javascript/638149/10 "2018-09-18T21:15:42Z")

</div>

You may need to adapt that code with the Drag Drop API: [https://developer.mozilla.org/en-US/docs/Web/API/HTML\_Drag\_and\_Drop\_API](https://developer.mozilla.org/en-US/docs/Web/API/HTML_Drag_and_Drop_API)

There are many ways to fake this behavior by detecting whether your mouse cursor is hovering over the drop area. We can look at some of these fake approaches if you the “recommended” approach using the Drag Drop API doesn’t work out 🙂

---

<div class="post-metadata">

### Author: ![brucenorton](https://yyz1.discourse-cdn.com/flex011/user_avatar/forum.kirupa.com/brucenorton/32/9288_2.png) [@brucenorton](https://forum.kirupa.com/u/brucenorton)
#### Post date: [September 18, 2018, 10:04pm UTC](https://forum.kirupa.com/t/create-a-draggable-element-in-javascript/638149/11 "2018-09-18T22:04:32Z")

</div>

Thanks Kirupa,  
My impression is that the Drag & Drop API does not work with touch events.  
I am designing for a 55" touch screen, like you might find in a mall or large office building.  
I am trying with collision detection, but so far no luck.  
If you could share a fake approach you might have come across, I would much appreciate it.

---

<div class="post-metadata">

### Author: ![brucenorton](https://yyz1.discourse-cdn.com/flex011/user_avatar/forum.kirupa.com/brucenorton/32/9288_2.png) [@brucenorton](https://forum.kirupa.com/u/brucenorton)
#### Post date: [September 19, 2018, 12:17pm UTC](https://forum.kirupa.com/t/create-a-draggable-element-in-javascript/638149/12 "2018-09-19T12:17:16Z")

</div>

P.S. This is the resource that helped me to get it working:  
https://codepen.io/glaubercorreaarticles/embed/preview/vRQYwZ?height=300&slug-hash=vRQYwZ&default-tabs=js,result&host=https://codepen.io&embed-version=2  
Specifically:

```
function dragEnd(e) {
     dropHandler(event.target, event.changedTouches[0].pageX, event.changedTouches[0].pageY);
    }

function dropHandler(element, coordX, coordY){
   if(element.parentNode.classList.contains(targetElement.id)){
    // console.log('good drop');
    dropped++;
  }else{
    //console.log('bad drop');
  }
}

```

Plus the important note to disable pointer events when dragging to access the target element underneath.  
.active{  
pointer-events: none;  
}

Thanks again.

---

<div class="post-metadata">

### Author: ![kirupa](https://yyz1.discourse-cdn.com/flex011/user_avatar/forum.kirupa.com/kirupa/32/11616_2.png) [@kirupa](https://forum.kirupa.com/u/kirupa)
#### Post date: [September 19, 2018, 5:59pm UTC](https://forum.kirupa.com/t/create-a-draggable-element-in-javascript/638149/13 "2018-09-19T17:59:11Z")

</div>

That is awesome! The approach I was thinking is where we listen for a **mouseover** or **touchover** event that fires over the drop area. When that happens, we can treat the drop as having succeeded when you release the mouse or touch. I’m just thinking out loud here, so what I said could be completely wrong 😛

---

<div class="post-metadata">

### Author: ![Alej](https://avatars.discourse-cdn.com/v4/letter/a/f14d63/32.png) [@Alej](https://forum.kirupa.com/u/Alej)
#### Post date: [October 22, 2018, 12:59pm UTC](https://forum.kirupa.com/t/create-a-draggable-element-in-javascript/638149/14 "2018-10-22T12:59:39Z")

</div>

Thanks for this posting. The code works great! But I’m having issues with the items going beyond the container border when using FireFox, Chrome and in my mobile. It does stop at the container border when using Microsoft Edge.  
Is there a fix for this issue?  
Again, thank you for this fourm.

---

<div class="post-metadata">

### Author: ![kirupa](https://yyz1.discourse-cdn.com/flex011/user_avatar/forum.kirupa.com/kirupa/32/11616_2.png) [@kirupa](https://forum.kirupa.com/u/kirupa)
#### Post date: [October 22, 2018, 4:50pm UTC](https://forum.kirupa.com/t/create-a-draggable-element-in-javascript/638149/15 "2018-10-22T16:50:03Z")

</div>

Can you post an example?

🙂

---

<div class="post-metadata">

### Author: ![dzimen](https://yyz1.discourse-cdn.com/flex011/user_avatar/forum.kirupa.com/dzimen/32/9338_2.png) [@dzimen](https://forum.kirupa.com/u/dzimen)
#### Post date: [October 31, 2018, 1:23pm UTC](https://forum.kirupa.com/t/create-a-draggable-element-in-javascript/638149/16 "2018-10-31T13:23:53Z")

</div>

How can I transform it so I can move several elements on the page? Here is the code: [https://pastebin.com/QV8UhHhC](https://pastebin.com/QV8UhHhC)

---

<div class="post-metadata">

### Author: ![mafiamaria](https://yyz1.discourse-cdn.com/flex011/user_avatar/forum.kirupa.com/mafiamaria/32/9357_2.png) [@mafiamaria](https://forum.kirupa.com/u/mafiamaria)
#### Post date: [November 14, 2018, 11:29am UTC](https://forum.kirupa.com/t/create-a-draggable-element-in-javascript/638149/17 "2018-11-14T11:29:19Z")

</div>

Omg this was a lifesaver, thank you so much!! It works great. I have many elements, and now it works like a charm. I only have one problem, I have to press the trackpad on my mac ones more to make it drop the element. It doesnt let go by itself. Do you have any clue how I can fix this problem?

---

<div class="post-metadata">

### Author: ![mafiamaria](https://yyz1.discourse-cdn.com/flex011/user_avatar/forum.kirupa.com/mafiamaria/32/9357_2.png) [@mafiamaria](https://forum.kirupa.com/u/mafiamaria)
#### Post date: [November 14, 2018, 1:48pm UTC](https://forum.kirupa.com/t/create-a-draggable-element-in-javascript/638149/19 "2018-11-14T13:48:12Z")

</div>

Sorry for spamming, but I found what’s wrong, it’s that I’m using png files. Then it doesn’t work properly. Do you know how I can make it work using the img tag? I need it to be files I’ve already made in illustrator

---

<div class="post-metadata">

### Author: ![namik](https://avatars.discourse-cdn.com/v4/letter/n/e0b2c6/32.png) [@namik](https://forum.kirupa.com/u/namik)
#### Post date: [November 14, 2018, 9:11pm UTC](https://forum.kirupa.com/t/create-a-draggable-element-in-javascript/638149/20 "2018-11-14T21:11:04Z")

</div>

Hi Kirupa,  
Thank you for your effort. Is it possible to re-arrange the code with many elements to use “element.style.top” and “element.style.left”. Because I need to keep the absolute coordinates of the elements fo later restructuring.  
Best regards.

---

<div class="post-metadata">

### Author: ![kirupa](https://yyz1.discourse-cdn.com/flex011/user_avatar/forum.kirupa.com/kirupa/32/11616_2.png) [@kirupa](https://forum.kirupa.com/u/kirupa)
#### Post date: [November 15, 2018, 8:33pm UTC](https://forum.kirupa.com/t/create-a-draggable-element-in-javascript/638149/21 "2018-11-15T20:33:03Z")

</div>

Just place your image files inside the `div` element that is currently the item that is being dragged around. The content inside it doesn’t matter at all 🙂

[Next page](https://forum.kirupa.com/t/create-a-draggable-element-in-javascript/638149.md?page=2)
