<!DOCTYPE html>
<html>
<head>
  <meta charset='utf-8' />
  <meta name='viewport' content='width=device-width, initial-scale=1' />

  <link rel='stylesheet' type='text/css' href='style.css' />
  <link href='https://fonts.googleapis.com/css?family=Montserrat' rel='stylesheet' />

  <title>DND</title>
</head>
<body>
  <div class='list'>
    <div class='list-item'>Задание 1</div>
      <div class='list-item'>Задание 2</div>
      <div class='list-item'>Задание 3ssssssssssssssssssssssssssssssssssssssssssssssssssssss</div>
      <div class='list-item'>Задание 4</div>
      <div class='list-item'>Задание 5</div>
      <div class='list-item'>Задание 6</div>
  </div>

  <div class='list'></div>

  <div class='list'>
    <div class='list-item'>Задание 1</div>
      <div class='list-item'>Задание 2</div>
      <div class='list-item'>Задание 5</div>
      <div class='list-item'>Задание 6</div>
  </div>

  <script src='script.js'></script>
</body>
</html>
body {
    padding: 20px;
}

.list {
    display: inline-block;
    vertical-align: top;
    width: 22%;
    padding: 13px;
    margin-right: 13px;
    background-color: #DFE1E6;
}

.list-item {
    box-sizing: border-box;
    padding: 9px 13px;
    margin: 8px 0;
    color: #000000;
    font-family: 'Montserrat', sans-serif;
    font-weight: 400;
    font-size: 13px;
    background-color: #FFFFFF;
    box-shadow: 0px 1px 4px rgba(9, 45, 66, 0.25);
    border-radius: 3px;
    user-select: none;
    transition: none;
    word-wrap: break-word;
}

.list-item:first-of-type {
    margin-top: 0;
}

.list-item:last-of-type {
    margin-bottom: 0;
}

.list-item:hover {
    cursor: pointer;
}

.list-item:last-of-type {
    margin-bottom: 0;
}

#list-item__cover {
    background-color: #C9D2D9;
    border-radius: 3px;
}
let dragItem = {};
let shift = {};

window.addEventListener('mousedown', dragStart);
window.addEventListener('mousemove', drag);
window.addEventListener('mouseup', dragEnd);

function dragStart(event) {
  const item = event.target;

  if (event.which !== 1 || !item.closest('.list-item')) return;
  
  dragItem.item = item;

  dragItem.downX = item.pageX;
  dragItem.downY = item.pageY;

  dragItem.item.style.width = dragItem.item.getBoundingClientRect().width + 'px';
  dragItem.item.style.height = dragItem.item.getBoundingClientRect().height + 'px';

  shift = {x: item.getBoundingClientRect().left - event.clientX, 
       y: item.getBoundingClientRect().top - event.clientY};
}

function drag(event) {
  if (!dragItem.item) return;
  
  const shadow = document.querySelector('#list-item__cover')
  if (shadow) shadow.remove()

  const item = dragItem.item;
  
  

  const itemCover = document.createElement('div');
  itemCover.id = 'list-item__cover';

  const list = findElement('list');
  const collisionItem = findElement('list-item');

  item.style.position = 'absolute';
  item.style.top = event.clientY + shift.y + 'px';
  item.style.left = event.clientX + shift.x + 'px';
  item.style.transform = 'rotate(5deg)';
  item.style.pointerEvents = 'none';
  item.style.zIndex = 2;
    
  if (list && list.children.length === 0) {
    if (list.children.length === 0 || (list.contains(item) && list.children.length === 1)) {
      list.appendChild(itemCover);
      itemCover.style.height = item.style.height;

      dragItem.cover = list.children.namedItem(itemCover.id);
      dragItem.list = list;
    } else {
      if (list.children.namedItem(itemCover.id) === null) return;
      list.children.namedItem(itemCover.id).remove();
    }
  } else if (collisionItem && collisionItem !== item) {
    const collisionItemList = collisionItem.parentElement;

    const prevElement = collisionItem.previousElementSibling;
    const nextElement = collisionItem.nextElementSibling;

    if (getCollideDirection(collisionItem) === 'top' && collideItems(item, collisionItem)) {
      if (prevElement && prevElement.id === itemCover.id) return;
      if (nextElement && nextElement.id === itemCover.id) nextElement.remove();

      collisionItemList.insertBefore(itemCover, collisionItem);
    }

    if (getCollideDirection(collisionItem) === 'bottom' && collideItems(item, collisionItem)) {
      if (nextElement && nextElement.id === itemCover.id) return;
      if (prevElement && prevElement.id === itemCover.id) prevElement.remove();

      insertAfter(itemCover, collisionItem);
    }

    itemCover.style.height = item.style.height;

    dragItem.cover = collisionItemList.children.namedItem(itemCover.id);
    dragItem.list = collisionItemList;
    dragItem.collisionItem = collisionItem;
  }

  if (dragItem.list) {
    for (let child of dragItem.list.children) {
      if (child.id === itemCover.id && !collideItems(dragItem.item, child)) {
        child.remove();
      }
    }
  }
}

function dragEnd(event) {
  if (!dragItem.item) return;

  const item = dragItem.item;
  const itemCover = dragItem.cover;

  if (itemCover && itemCover.parentElement) {
    item.setAttribute('style', 'none');
    itemCover.outerHTML = item.outerHTML;
    item.remove();
  } else {
    item.setAttribute('style', 'none');
  }

  dragItem.item = null;
  dragItem.list = null;
  dragItem.cover = null;
}

function findElement(attributeValue) {
  const event = window.event;
  const element = document.elementFromPoint(event.clientX, event.clientY);

  if (element && (element.className === attributeValue || element.id === attributeValue)) return element
}

function getCollideDirection(item) {
  const itemCoords = item.getBoundingClientRect();
  const event = window.event;

  if ((event.clientY > itemCoords.top) && 
    (event.clientY < itemCoords.top + itemCoords.height / 2)) return 'top';

  if ((event.clientY < itemCoords.bottom) && 
    (event.clientY > itemCoords.top + itemCoords.height / 2)) return 'bottom';
}

function collideItems(item1, item2) {
  const item1Coords = item1.getBoundingClientRect();
  const item2Coords = item2.getBoundingClientRect();

  return !((item1Coords.top + item1Coords.height < item2Coords.top)    ||
         (item1Coords.top > item2Coords.top + item2Coords.height)      ||
         (item1Coords.left + item1Coords.width / 2 < item2Coords.left) ||
         (item1Coords.left + item1Coords.width / 2 > item2Coords.right));
}

function insertAfter(element, refElement) {
  return refElement.parentElement.insertBefore(element, refElement.nextElementSibling);
}

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.