<!-- You'd need to set up something different for touch devices though -->
<h1>Drag and drop example </h1>
<div class="wrap">
    <div id='phrase'>
      <!-- using a form will help enforce sensible entries -->
      <form id='calculate-position'>
        <label for='rowInput'>Enter a row A - H</label>
        <input type='text' id='rowInput' pattern='[a-hA-H]' placeholder='Enter Row' required>
        <label for='colInput'>Enter a column 1 - 12</label>
        <input type='number' id='colInput' min='1' max='12' pattern='[0-9]' placeholder=' Enter Column' required>
        <button id='calculate'>Calculate</button>
      </form>
      <output class='target'>The cell number is <b id='cellnum'>?</b></output>
      <div id='words'>
        <button type='button' id='move-text' type='button'>Move Text Content!</button>
        <!-- remove whitespace from  inside div html and then we can use :empty in css to change background -->
        <div data-id='01'><span class='words' data-id='01'>H1 text</span></div>
        <div data-id='02'><span class='words' data-id='02'>H2 text</span></div>
        <div data-id='03'><span class='words' data-id='03'>H3 text</span></div>
        <div data-id='04'><span class='words' data-id='04'>H4 text</span></div>
        <div data-id='05'><span class='words' data-id='05'>H5 text</span></div>
        <div data-id='06'><span class='words' data-id='06'>H6 text</span></div>
        <div data-id='07'><span class='words' data-id='07'>G1 text</span></div>
        <div data-id='08'><span class='words' data-id='08'>G2 text</span></div>
        <div data-id='09'><span class='words' data-id='09'>G3 text</span></div>
        <div data-id='10'><span class='words' data-id='10'>G4 text</span></div>
      </div>
    </div>

  <div id="drop-em" class="grid">
    <div class="item">
      <div class="content"></div><!-- must have no spaces inside .content -->
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
  </div>
</div>
html {
  box-sizing: border-box;
}
*,
*:before,
*:after {
  box-sizing: inherit;
}
body {
  counter-reset: columnCount 1 alphaCount cellCount;
}
h1 {
  text-align: center;
}
.wrap {
  display: flex;
  gap: 2rem;
  position:relative;
  padding-left:220px;
}

.grid {
  margin: auto;
  display: grid;
  flex: 1 0 0;
  grid-template-columns: repeat(12, 1fr);
  padding-top: 1.5rem;
}

.item {
  position: relative;
  background-color: #f9f9f9;
  border: 1px solid grey;
  aspect-ratio: 1/1;
  counter-increment: columnCount;
  min-width: 0;
  transition: background 1s ease;
}

.item:nth-of-type(12n + 1) {
  counter-increment: alphaCount;
}

.item:nth-of-type(12n + 1)::before {
  content: counter(alphaCount, upper-alpha);
  position: absolute;
  display: flex;
  align-items: center;
  top: 0;
  bottom: 0;
  left: -1.75rem;
  color: red;
  pointer-events: none;
}

.item:nth-of-type(n + 13)::after {
  display: none;
}

.item::after {
  content: counter(columnCount);
  position: absolute;
  left: 0;
  right: 0;
  text-align: center;
  top: -1.75rem;
  color: red;
  pointer-events: none;
}

.content {
  display: flex;
  flex-direction: column;
  justify-content: center;
  width: 100%;
  height: 100%;
  overflow: auto;
  color: #000;
  padding: 1rem;
  word-wrap: break-word;
  counter-increment: cellCount;
}

.words {
  cursor: move;
  transition: padding 0.5s ease;
}

.content:has(.ui-draggable-dragging) {
  overflow: visible;
}

.ui-droppable-active .content {
  overflow: visible;
}

.words.ui-draggable-dragging {
  background: blue;
  padding: 5px 10px;
  border-radius: 6px;
  z-index: 999;
  color: #fff;
  display: block;
  width: 50px;
  height: 50px;
  overflow: hidden;
}

#phrase {
  position:absolute;
  left:0;
  top:0;
  bottom:0;
  color: #fff;
  width:150px;
  z-index: 2;
  margin:1rem 0 .5rem;
}

form#calculate-position, /* flex moved from #phase here */
#words { 
  display: flex;
  flex-direction: column;
}

#words > div { /* changed id to #words */
  margin: 0 0 10px;
  width:150px;
  padding: 5px 10px;
  background: #007bff;
  border: 2px solid #007bff;
  border-radius: 6px;
  color: #fff;
}

#words > div:empty { /* changed id to #words */
  background: #fff;
  border-style: dashed;
  padding: 0px 25px;
  min-height: 30px;
}

.moved {
  animation: fade 3s ease;
}
@keyframes fade {
  0% {
    opacity: 0;
  }
  50% {
    opacity: 1;
    background: red;
  }
}

.item .content::before {
  content: counter(cellCount);
  position: absolute;
  top: 2px;
  left: 2px;
  font-size: smaller;
  color: #666;
  border-radius: 50%;
  border: 1px solid red;
  background: white;
  width: 1.2rem;
  height: 1, 2rem;
  display: grid;
  place-items: center;
}

#move-text.disabled{
  cursor:none;
  pointer-events:none;
  opacity:0.5;
}

#phrase:has(.ui-droppable-active){
  overflow:visible;
}


input,
button,
label,
output.target { /* changed to output */
  display: block;
  margin: 0 0 0.4rem;
  color:#000;
}

output.target {margin:0 0 1rem} /* changed to output */
/*

Requires jquery + UI

https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js

https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js

*/

$(".words").draggable({
  revert: function (event, ui) {
    var bRevertingPhrase = this.closest("#drop-em");

    if (!bRevertingPhrase.length) {
      var phraseID = $(this).data("id");
      var phraseHomeID = $(this).parent().data("id");

      //If the child and parent ids don't match, we move the child to the correct parent
      if (phraseID !== phraseHomeID) {
        var correctCell = $("#phrase").find("div[data-id='" + phraseID + "']");
        correctCell.prepend(this);
      }
    }
    return !event;
  }
});
$("#drop-em > div").droppable({
  drop: function (ev, ui) {
    $(ui.draggable)
      .detach()
      .css({ top: 0, left: 0 })
      .appendTo($(this).find(".content:empty"));
    $("#move-text").addClass("disabled");
  }
});
$("#phrase > div").droppable({
  drop: function (ev, ui) {
    $(ui.draggable).detach().css({ top: 0, left: 0 }).prependTo(this);
  }
});

var reOrder = [];

function fill(startPos = 1) {
  const cells = document.querySelectorAll('#words > div > span');
  let newLoc;
  let myIndex = 0;

  cells.forEach((cell, index) => {
    newLoc = document.querySelector(
      `.item:nth-child(${reOrder[myIndex + startPos - 1]}) .content `,
    );

    newLoc.append(cell);
    newLoc.classList.add('moved');

    if (index + startPos - 1 === 95) {
      startPos = 0;
      myIndex = 0;
    }

    myIndex += 1;
  });
}

function reArrange(limit1, limit2) {
  for (let loop = 0; loop < 8; loop++) {
    for (let i = 0; i < 6; i++) {
      reOrder.push(limit1 + i);
    }
    limit1 = limit1 - 12;
  }
  for (let loop = 0; loop < 8; loop++) {
    for (let j = 0; j < 6; j++) {
      reOrder.push(limit2 + j);
    }
    limit2 = limit2 - 12;
  }
}

reArrange(85, 91);


/* get cell number */

/**
 * Calculates the row number based on the character provided, using a start value and step size.
 * @param {string} char - The character to calculate the row number for.
 * @param {number} [start=42] - The starting row number.
 * @param {number} [step=-6] - The step size to increment/decrement for each character.
 * @returns {number} The calculated row number based on the character provided.
 */
function calcRowFromChar(char, start = 42, step = -6) {
  // e.g. 'a' → upperCase 'A' → charCode is 65 → minus 65 → 0
  const charPosInAlphabet = char.toUpperCase().charCodeAt(0) - 65;
  return start + charPosInAlphabet * step;
}

// A module pattern to keep startPos out of the
// global context and only where it is needed
function createHandlers() {
  // startPos is local to createHandlers and only
  // available to the returned handlers
  let startPos = 1;

  return {
    calculateStart(event) {
      // prevent actually submitting the form
      event.preventDefault();
      const start = 42
      // we can access the form elements directly from the form, without querySelecting
      const { rowInput, colInput } = event.target.elements;
      const rowNum = calcRowFromChar(rowInput.value, start);
      const colNum = Number(colInput.value);

      startPos = (colNum < 7)
        ? rowNum + colNum
        : rowNum + start + colNum;

      document.querySelector('#cellnum').textContent = startPos;
    },

    moveToGrid(event) {
      // disable button
      event.target.classList.add('disabled');
      // pass in startPos to fill function instead
      fill(startPos);
    }
  };
}

const handlers = createHandlers();

const calculateButton = document.querySelector('#calculate-position');
calculateButton.addEventListener('submit', handlers.calculateStart);

const moveTextBtn = document.querySelector('#move-text');
moveTextBtn.addEventListener('click', handlers.moveToGrid, { once: true });
Run Pen

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

  1. https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js
  2. https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js