How to make a draggable div resize-able on all 4 corners with pure javascript?

I noticed these resize pointers in the css spec…

https://drafts.csswg.org/css-ui-3/#valdef-cursor-se-resize

Is there a CSS shortcut for 4 corner resizability similar to the one corner (‘resize: both’) method?
If not, are there known conflicts when combining resizability with a draggable div?

My starting point was here…

https://www.w3schools.com/howto/howto_js_draggable.asp

Any help navigating the posX, posY is appreciated.

const myDiv = document.getElementById('mydiv')
//Make the DIV element draggagle:
dragElement(myDiv);
let isResizing = false;

function dragElement(elmnt) {
  let pos1 = 0,
    pos2 = 0,
    pos3 = 0,
    pos4 = 0;
  if (document.getElementById(elmnt.id + "header")) {
    //if present, the header is where you move the DIV from:
    document.getElementById(elmnt.id + "header").onmousedown = dragMouseDown;
  } else {
    //otherwise, move the DIV from anywhere inside the DIV:
    elmnt.onmousedown = dragMouseDown;
  }

  function dragMouseDown(e) {
    if (!isResizing) {
      e = e || window.event;
      e.preventDefault();
      // get the mouse cursor position at startup:
      pos3 = e.clientX;
      pos4 = e.clientY;
      document.onmouseup = closeDragElement;
      // call a function whenever the cursor moves:
      document.onmousemove = elementDrag;
    }
  }

  function elementDrag(e) {
    if (!isResizing) {

      e = e || window.event;
      e.preventDefault();
      // calculate the new cursor position:
      pos1 = pos3 - e.clientX;
      pos2 = pos4 - e.clientY;
      pos3 = e.clientX;
      pos4 = e.clientY;
      // set the element's new position:
      elmnt.style.top = (elmnt.offsetTop - pos2) + "px";
      elmnt.style.left = (elmnt.offsetLeft - pos1) + "px";
    }
  }

  function closeDragElement() {
    //stop moving when mouse button is released:
    document.onmouseup = null;
    document.onmousemove = null;
  }
}

const resizers = document.querySelectorAll('.resizer')
let currentResizer

for (let resizer of resizers) {
  resizer.addEventListener('mousedown', mouseDown)

  function mouseDown(e) {
    currentResizer = e.target
    isResizing = true;

    let posX = e.clientX;
    let posY = e.clientY;
    myDiv.addEventListener('mousemove', mouseMove)
    myDiv.addEventListener('mouseup', mouseUp)

    function mouseMove(e) {
      const rect = myDiv.getBoundingClientRect()
      if (currentResizer.classList.contains('se')) {
        console.log(currentResizer.classList.value)

        myDiv.style.width = rect.width - (posX - e.clientX) + 'px';
        myDiv.style.height = rect.height - (posY - e.clientY) + 'px';
      } else if (currentResizer.classList.contains('sw')) {
        console.log(currentResizer.classList.value)

        myDiv.style.width = rect.width + (posX - e.clientX) + 'px';
        myDiv.style.height = rect.height - (posY - e.clientY) + 'px';
        myDiv.style.left = rect.left - (posX - e.clientX) + 'px';

      } else if (currentResizer.classList.contains('ne')) {
        console.log(currentResizer.classList.value)

        myDiv.style.width = rect.width - (posX - e.clientX) + 'px';
        myDiv.style.height = rect.height + (posY - e.clientY) + 'px';
        myDiv.style.top = rect.top - (posY - e.clientY) + 'px';

      } else {
        console.log(currentResizer.classList.value)

        myDiv.style.width = rect.width + (posX - e.clientX) + 'px';
        myDiv.style.height = rect.height + (posY - e.clientY) + 'px';
        myDiv.style.top = rect.top - (posY - e.clientY) + 'px';
        myDiv.style.left = rect.left - (posX - e.clientX) + 'px';

      }
      posX = e.clientX;
      posY = e.clientY;
    }

    function mouseUp(e) {
      myDiv.removeEventListener('mousemove', mouseMove)
      myDiv.removeEventListener('mouseup', mouseUp)
      isResizing = false
    }
  }
}
* {
  margin: 0;
}

#mydiv {
  position: absolute; /* NECESSARY */
  background-color: whitesmoke;
  text-align: center;
  border: 1px solid #222;
  height: 200px;
  width: 200px;
  /* resize: both; /* CSS RESIZE */
  overflow: hidden; /* CSS RESIZE */
}

#mydivheader {
  padding: 10px;
  cursor: move;
  background-color: dodgerblue;
  color: #fff;
}

#content {
  color: #000;
  margin: 0px;
  background-color: whitesmoke;
}


/* ::-webkit-resizer {
  position: absolute;
  height: 20px;
  width: 20px;
  border-top-left-radius: 25px;
  background-color: #dd0;
  z-index: 2;
} */

.resizer {
  position: absolute;
  height: 20px;
  width: 20px;
  background-color: #dd0;
  z-index: 2;
}

.resizer.nw {
  top: -1px;
  left: -1px;
  cursor: nw-resize;
  border-bottom-right-radius: 25px;
}

.resizer.ne {
  top: -1px;
  right: -1px;
  cursor: ne-resize;
  border-bottom-left-radius: 25px;
}

.resizer.sw {
  bottom: -1px;
  left: -1px;
  cursor: sw-resize;
  border-top-right-radius: 25px;
}

.resizer.se {
  bottom: -1px;
  right: -1px;
  cursor: se-resize;
  border-top-left-radius: 25px;
}
<div id="mydiv">
  <div class='resizer ne'></div>
  <div class='resizer nw'></div>
  <div class='resizer sw'></div>
  <div class='resizer se'></div>

  <div id="mydivheader">Click here to move

    <div id='content'>

      <div id='image-container'><img height='auto' width='100%' src='https://picsum.photos/600' /></div>

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

18 thoughts on “How to make a draggable div resize-able on all 4 corners with pure javascript?”

Leave a Comment