diff --git a/package.json b/package.json
index c0ad805589a010c35b031b74a3172677596c1c02..2df9369261372a06693e06c24089e20778ec0e4d 100644
--- a/package.json
+++ b/package.json
@@ -39,6 +39,7 @@
     "vuepress": "^1.9.8"
   },
   "dependencies": {
-    "uuid": "^9.0.0"
+    "uuid": "^9.0.0",
+    "vue-interactjs": "^0.1.10"
   }
 }
diff --git a/src/DragContainer.vue b/src/DragContainer.vue
index df4a8657f356a40f05a31e68f9a3ccb836e9d43a..6c2b6441dc6bd9fbdf268e9a8e0cd19aafadce7f 100644
--- a/src/DragContainer.vue
+++ b/src/DragContainer.vue
@@ -1,13 +1,15 @@
 <template>
-  <div
+  <interact
     @dragstart="handleDragStart"
+    @dragmove="handleDragMove"
     :draggable="!isDisabled"
     id="wrapper"
     ref="wrapper"
     @dragend="handleDragEnd"
+    :data-transfer="dataTransferString"
   >
     <slot></slot>
-  </div>
+  </interact>
 </template>
 
 <script>
@@ -16,26 +18,27 @@ export default {
   methods: {
     handleDragStart(event) {
       if (this.isDisabled) return;
-      this.$refs.wrapper.style.cursor = "grabbing";
       let rect = event.target.getBoundingClientRect();
-      event.dataTransfer.setData(
-        "vueDrag/gridItem",
-        JSON.stringify({
-          key: this.dragID,
-          x: this.x,
-          y: this.y,
-          w: this.w,
-          h: this.h,
-          data: this.data,
-          context: this.context,
-          originGridId: this.gridId,
-          mouseX: event.clientX - rect.x - rect.width / (2 * this.w), // relative to center of the top left square
-          mouseY: event.clientY - rect.y - rect.height / (2 * this.h),
-        })
-      );
+      this.dataTransfer = {
+        key: this.dragID,
+        x: this.x,
+        y: this.y,
+        w: this.w,
+        h: this.h,
+        data: this.data,
+        context: this.context,
+        originGridId: this.gridId,
+        mouseX: event.clientX - rect.x - rect.width / (2 * this.w), // relative to center of the top left square
+        mouseY: event.clientY - rect.y - rect.height / (2 * this.h),
+      };
     },
     handleDragEnd() {
-      this.$refs.wrapper.style.cursor = "grab";
+      this.offsetX = 0;
+      this.offsetY = 0;
+    },
+    handleDragMove(event) {
+      this.offsetX += event.dx;
+      this.offsetY += event.dy;
     },
   },
   props: {
@@ -96,6 +99,16 @@ export default {
     cursor() {
       return this.disabled ? "auto" : "grab";
     },
+    dataTransferString() {
+      return JSON.stringify(this.dataTransfer);
+    },
+  },
+  data() {
+    return {
+      dataTransfer: {},
+      offsetX: 0,
+      offsetY: 0,
+    };
   },
 };
 </script>
@@ -106,5 +119,9 @@ export default {
   grid-row: v-bind(getY) / span v-bind(h);
   display: v-bind(getDisplay);
   cursor: v-bind(cursor);
+  transform: translate(
+    calc(1px * v-bind(offsetX)),
+    calc(1px * v-bind(offsetY))
+  );
 }
 </style>
diff --git a/src/DragGrid.vue b/src/DragGrid.vue
index 78a6cb76daafc994e5a724dee99252bdc3e96875..2b926ef1d041df8c54be187f05d3bf84ff5ba3ff 100644
--- a/src/DragGrid.vue
+++ b/src/DragGrid.vue
@@ -1,6 +1,7 @@
 <template>
-  <div
-    @dragover.prevent="disabled ? undefined : handleDragOver($event)"
+  <interact
+    droppable
+    @dropmove="disabled ? undefined : handleDragOver($event)"
     @drop.prevent="disabled ? undefined : handleDrop($event)"
     @dragleave="$refs.highlightContainer.style.display = 'none'"
     class="grid"
@@ -47,7 +48,7 @@
       </GridItem>
     </template>
     <slot></slot>
-  </div>
+  </interact>
 </template>
 
 <script>
@@ -143,12 +144,12 @@ export default {
       return true;
     },
     handleDragOver(event) {
-      let data = event.dataTransfer.getData("vueDrag/gridItem");
+      let data = event.relatedTarget.dataset.transfer;
       if (!data) return;
       let element = JSON.parse(data);
       let coords = this.getCoords(
-        event.clientX - element.mouseX,
-        event.clientY - element.mouseY
+        event.dragEvent.client.x - element.mouseX,
+        event.dragEvent.client.y - element.mouseY
       );
 
       if (element.context !== this.context || this.noHighlight) {
@@ -179,7 +180,7 @@ export default {
     },
     handleDrop(event) {
       this.$refs.highlightContainer.style.display = "none";
-      let data = event.dataTransfer.getData("vueDrag/gridItem");
+      let data = event.relatedTarget.dataset.transfer;
       if (!data) return;
       let element = JSON.parse(data);
 
@@ -190,8 +191,8 @@ export default {
       }
 
       let coords = this.getCoords(
-        event.clientX - element.mouseX,
-        event.clientY - element.mouseY
+        event.dragEvent.client.x - element.mouseX,
+        event.dragEvent.client.y - element.mouseY
       );
 
       let newPositionValid = true;
@@ -221,6 +222,8 @@ export default {
 
         elementCopy.context = undefined;
         elementCopy.originGridId = undefined;
+        elementCopy.mouseX = undefined;
+        elementCopy.mouseY = undefined;
 
         valueCopy.push(elementCopy);
         this.$emit("input", valueCopy);
@@ -239,11 +242,20 @@ export default {
 
       this.$emit("itemChanged", element);
     },
+    clamp: (min, num, max) => Math.min(Math.max(num, min), max),
     getCoords(x, y) {
       let rect = this.$el.getBoundingClientRect();
       return {
-        x: Math.ceil((x - rect.x) / (rect.width / this.cols)),
-        y: Math.ceil((y - rect.y) / (rect.height / this.rows)),
+        x: this.clamp(
+          1,
+          Math.ceil((x - rect.x) / (rect.width / this.cols)),
+          this.cols
+        ),
+        y: this.clamp(
+          1,
+          Math.ceil((y - rect.y) / (rect.height / this.rows)),
+          this.rows
+        ),
       };
     },
     getInt(property, item) {
@@ -301,5 +313,6 @@ export default {
   min-width: 100px;
   min-height: 100px;
   gap: 1em;
+  touch-action: none;
 }
 </style>
diff --git a/src/index.js b/src/index.js
index 7d9aa6ed2162895c67d6cf60c1d77bf2b21dd5ba..e29a2d81b8d4782dd12752065b996dd7d813eebe 100644
--- a/src/index.js
+++ b/src/index.js
@@ -1,4 +1,8 @@
 import components from "./components";
+import Vue from "vue";
+import VueInteractJs from "vue-interactjs";
+
+Vue.use(VueInteractJs);
 
 const plugin = {
   install(Vue) {