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.
Codebase
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Draggable</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div class="draggable-object">
<div class="draggable-subject">Draggable</div>
</div>
<script src="app.js"></script>
</body>
</html>
index.html is no different from the previous example.
style.css
@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.
app.js
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) {
e.preventDefault()
document.onmousemove = drag
}
function drag(e) {
positionLeft += e.movementX
positionTop += e.movementY
draggableObject.style.left = clamp(positionLeft, 0, positionLeftMax) + unit
draggableObject.style.top = clamp(positionTop, 0, positionTopMax) + unit
}
function endDrag() {
document.onmousemove = null
}
setMaxPositions()
draggableSubject.onmousedown = startDrag
draggableSubject.onmouseup = endDrag
Note
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.