<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <link rel="stylesheet" href="dnd.css" />
  </head>
  <body>
    <div class="wrapper">
      <header>
        <h1>Drag and Drop</h1>
      </header>
      <main>
        <div class="list-wrapper">
          <div class="column">
            <div class="column-header">To Do</div>
            <div class="card-wrapper">
              <div class="card" draggable="true">
                <div class="header">
                  <div class="title">
                    <span>๐Ÿƒโ€โ™‚๏ธ ์šด๋™ํ•˜๊ธฐ</span>
                  </div>
                </div>
                <div class="body">
                  <p>์•„์นจ์— ์ผ์–ด๋‚˜ ์šด๋™์„ ํ•œ๋‹ค.</p>
                </div>
                <div class="caption">padosum</div>
              </div>
              <div class="card" draggable="true">
                <div class="header">
                  <div class="title">
                    <span>๐Ÿง‘โ€๐Ÿณ ์ ์‹ฌ ๋งŒ๋“ค๊ธฐ</span>
                  </div>
                </div>
                <div class="body">
                  <p>๋ฎ๋ฐฅ์„ ๋งŒ๋“ ๋‹ค.</p>
                </div>
                <div class="caption">padosum</div>
              </div>
            </div>
          </div>
          <div class="column">
            <div class="column-header">Doing</div>
            <div class="card-wrapper">
              <div class="card" draggable="true">
                <div class="header">
                  <div class="title">๐Ÿ„โ€โ™‚๏ธ ์„œํ•‘ํ•˜๊ธฐ</div>
                </div>
                <div class="body">
                  <p>๐Ÿ„โ€โ™‚๏ธ ๐Ÿ„โ€โ™€๏ธ ๐Ÿ„</p>
                </div>
                <div class="caption">padosum</div>
              </div>
            </div>
          </div>
          <div class="column">
            <div class="column-header">Done</div>
            <div class="card-wrapper">
              <div class="card" draggable="true">
                <div class="header">
                  <div class="title">๐Ÿง‘โ€๐ŸŽ“ ๊ณต๋ถ€ํ•˜๊ธฐ</div>
                </div>
                <div class="body">
                  <p>
                    https://developer.mozilla.org/ko/docs/Web/API/HTMLElement/drag_event
                  </p>
                </div>
                <div class="caption">padosum</div>
              </div>
            </div>
          </div>
        </div>
      </main>
      <footer></footer>
    </div>
    <!-- <script
      id="DragDropTouch"
      src="https://bernardo-castilho.github.io/DragDropTouch/DragDropTouch.js"
    ></script> -->
    <script src="dnd.js"></script>
  </body>
</html>
body {
  background-color: #f5f5f7;
}

.wrapper {
  padding: 0 80px;
  height: 100%;
}

.list-wrapper {
  display: flex;
  gap: 20px;
}

.column {
  width: 350px;
}

.column > .column-header {
  padding: 0 8px;
}

.card {
  padding: 16px;
  margin-top: 10px;
  border-radius: 6px;
  background-color: white;
  box-shadow: 0px 1px 30px rgb(224 224 224 / 30%);
  cursor: move;
}

.card.dragging {
  opacity: 0.8;
  box-shadow: 0px 0px 4px rgba(204, 204, 204, 0.5),
    0px 2px 4px rgba(0, 0, 0, 0.25);
}

.card.over {
  opacity: 0.4;
  border: 1px solid #0075de;
}

.card .title {
  font-size: 16px;
  font-weight: 700;
}

.card .body {
  font-size: 14px;
  overflow-wrap: break-word;
}

.card .caption {
  font-size: 12px;
  color: #bdbdbd;
}
document.addEventListener('DOMContentLoaded', () => {
  const list = document.querySelector('.list-wrapper')

  list.addEventListener('dragstart', e => {
    const card = e.target.closest('.card')
    if (!card) return

    card.classList.add('dragging')
  })

  list.addEventListener('dragend', e => {
    const card = e.target.closest('.card')
    if (!card) return

    e.target.classList.remove('dragging')
    e.target.classList.remove('over')
  })

  list.addEventListener('dragenter', e => {
    const card = e.target.closest('.card')
    if (!card) return
    e.target.classList.add('over')
  })

  list.addEventListener('dragleave', e => {
    const card = e.target.closest('.card')
    if (!card) return
    e.target.classList.remove('over')
  })

  list.addEventListener('dragover', e => {
    e.preventDefault()
    const column = e.target.closest('.column')
    if (!column) return

    console.log('dragover')

    const dragging = document.querySelector('.dragging')
    const pointedEl = document.elementFromPoint(e.clientX, e.clientY)
    const closestCard = pointedEl.closest('.card')
    if (closestCard) {
      closestCard.before(dragging)
    } else {
      const cardWrapper = column.querySelector('.card-wrapper')
      cardWrapper.appendChild(dragging)
    }
  })

  list.addEventListener('drop', e => {
    e.preventDefault()
    const column = e.target.closest('.column')
    if (!column) return

    console.log('drop!')
  })
})

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.