Back to CSS Tags & Chips Drag to Reorder Light JS
Share
.ctc-drag { display: flex; gap: 8px; list-style: none; margin: 0; padding: 0; }

.ctc-drag-chip { display: inline-flex; align-items: center; padding: 8px 16px; background: #1f1f2e; color: #c4b5fd; border: 1px solid rgba(124,108,255,0.35); border-radius: 999px; font: 600 12px/1 system-ui, sans-serif; cursor: grab; user-select: none; touch-action: none; transition: transform 0.18s ease, background 0.2s; }

.ctc-drag-chip:hover { background: rgba(124,108,255,0.18); }

.ctc-drag-chip.is-dragging { cursor: grabbing; background: #7c6cff; color: #fff; z-index: 2; transition: none; }

.ctc-drag-chip:focus-visible { outline: 2px solid #a78bfa; outline-offset: 2px; }
<ul class="ctc-drag" role="listbox" aria-label="Reorder tags">
  <li class="ctc-drag-chip" tabindex="0" data-ctc-drag>Frontend</li>
  <li class="ctc-drag-chip" tabindex="0" data-ctc-drag>Backend</li>
  <li class="ctc-drag-chip" tabindex="0" data-ctc-drag>DevOps</li>
</ul>
(function () {
  document.querySelectorAll('.ctc-drag').forEach(function (list) {
    var dragged = null;
    list.querySelectorAll('[data-ctc-drag]').forEach(function (chip) {
      chip.addEventListener('pointerdown', function (e) {
        dragged = chip;
        chip.classList.add('is-dragging');
        chip.setPointerCapture(e.pointerId);
      });
      chip.addEventListener('pointermove', function (e) {
        if (dragged !== chip) return;
        var siblings = Array.from(list.children).filter(function (c) { return c !== chip; });
        for (var i = 0; i < siblings.length; i++) {
          var rect = siblings[i].getBoundingClientRect();
          if (e.clientX > rect.left && e.clientX < rect.right) {
            var dragRect = chip.getBoundingClientRect();
            if (e.clientX < rect.left + rect.width / 2) {
              list.insertBefore(chip, siblings[i]);
            } else {
              list.insertBefore(chip, siblings[i].nextSibling);
            }
            break;
          }
        }
      });
      chip.addEventListener('pointerup', function () {
        chip.classList.remove('is-dragging');
        dragged = null;
      });
      chip.addEventListener('keydown', function (e) {
        var siblings = Array.from(list.children);
        var idx = siblings.indexOf(chip);
        if (e.key === 'ArrowLeft' && idx > 0) {
          e.preventDefault();
          list.insertBefore(chip, siblings[idx - 1]);
          chip.focus();
        } else if (e.key === 'ArrowRight' && idx < siblings.length - 1) {
          e.preventDefault();
          list.insertBefore(chip, siblings[idx + 1].nextSibling);
          chip.focus();
        }
      });
    });
  });
})();
Live preview Edit any tab — preview updates live Ready