Zac Fukuda

Make HTML Element Draggable within Browser Window

This is an extended version of previous example Make Html Element Draggable with Bar, to confine a draggable html element in the visible area of window.


<!DOCTYPE html>
<html lang="en">
  <meta charset="utf-8">
  <link rel="stylesheet" href="style.css">
  <div class="draggable-object">
    <div class="draggable-subject">Draggable</div>
  <script src="app.js"></script>

index.html is no different from the previous example.

@charset "utf-8";

.draggable-object {
  position: absolute;

.draggable-subject {
  cursor: grab;
.draggable-subject:active {
  cursor: grabbing;

/* Only for demo */
html, body {
  width: 100%;
  height: 100%;

body {
  margin: 0;
  font-family: sans-serif;

.draggable-object {
  width: 160px;
  height: 160px;
  border: 1px solid #ddd;
  border-radius: 2px;
  display: inline-block;

.draggable-subject {
  background: #f0f0f0;
  padding: 4px 8px;

style.css is also no different from the previous example.

const draggableObject = document.querySelector('.draggable-object')
const draggableSubject = document.querySelector('.draggable-subject')
const unit = 'px'
let positionLeft = 0, positionTop = 0
let positionLeftMax = 9999, positionTopMax = 9999

function setMaxPositions() {
  positionLeftMax = innerWidth - draggableObject.offsetWidth
  positionTopMax = innerHeight - draggableObject.offsetHeight

function clamp(value, min, max) {
  return Math.min(max, Math.max(min, value))

function startDrag(e) {
  document.onmousemove = drag

function drag(e) {
  positionLeft += e.movementX
  positionTop += e.movementY = clamp(positionLeft, 0, positionLeftMax) + unit = clamp(positionTop, 0, positionTopMax) + unit

function endDrag() {
  document.onmousemove = null

draggableSubject.onmousedown = startDrag
draggableSubject.onmouseup = endDrag


The JavaScript code above has one issue.

When you release a mouse while your pointer is outside browser window, mouseup event will not be triggered. This causes the browser behavior that even when your pointer goes back inside browser—with mouse releasing—the mousemove event is still in effect. The draggable element keeps tracing your pointer. In order to cancel the mousemove event, you have to once again mousedown the bar, then fire mouseup.