Case ce-0300-firefox-drag-drop-duplicate-elements-en · Scenario scenario-drag-drop-duplicate

Dragging contenteditable="false" elements causes duplication in Firefox

OS: Windows 10-11 Device: Desktop or Laptop Any Browser: Firefox 120+ Keyboard: US QWERTY Status: draft
drag-drop contenteditable-false firefox duplicate nested

Phenomenon

In Firefox, dragging elements with contenteditable="false" within a contenteditable container can result in duplicate elements upon dropping. This issue is not observed in Chrome.

Reproduction example

  1. Open Firefox browser on Windows.
  2. Create a contenteditable element containing a contenteditable="false" element with draggable="true".
  3. Drag the non-editable element to a new position within the container.
  4. Drop the element.
  5. Observe that the element is duplicated instead of moved.

Observed behavior

  • Dragging a contenteditable="false" element creates a duplicate
  • The original element remains in its position
  • A copy is created at the drop location
  • This only occurs in Firefox

Expected behavior

  • Dragging should move the element, not duplicate it
  • The original element should be removed from its position
  • Behavior should be consistent with other browsers

Impact

  • Data integrity: Unintended element duplication
  • User confusion: Users may not understand why elements are duplicated
  • Content corruption: Multiple duplicates can accumulate over time

Browser Comparison

  • Firefox: Elements are duplicated (this issue)
  • Chrome: Elements are moved correctly
  • Safari: Elements are moved correctly
  • Edge: Elements are moved correctly

Notes and possible direction for workarounds

  • Prevent default behavior: Call event.preventDefault() in drag event handlers
  • Manual cleanup: Remove the original element after drop
  • Custom drag handler: Implement custom drag-and-drop logic to control behavior

Code example

const editor = document.querySelector('div[contenteditable]');
const draggableElements = editor.querySelectorAll('[contenteditable="false"][draggable="true"]');

draggableElements.forEach((el) => {
  let draggedElement = null;
  
  el.addEventListener('dragstart', (e) => {
    draggedElement = el;
    // Set drag data to prevent default behavior
    e.dataTransfer.setData('text/plain', ' ');
    e.dataTransfer.effectAllowed = 'move';
  });
  
  el.addEventListener('dragover', (e) => {
    e.preventDefault();
    e.dataTransfer.dropEffect = 'move';
  });
  
  el.addEventListener('drop', (e) => {
    e.preventDefault();
    
    if (draggedElement && draggedElement !== el) {
      // Get drop position
      const selection = window.getSelection();
      const range = selection.rangeCount > 0 ? selection.getRangeAt(0) : null;
      
      if (range) {
        // Clone element
        const clone = draggedElement.cloneNode(true);
        
        // Insert at drop position
        range.insertNode(clone);
        range.collapse(false);
        
        // Remove original element (Firefox workaround)
        if (draggedElement.parentNode) {
          draggedElement.parentNode.removeChild(draggedElement);
        }
        
        // Update selection
        selection.removeAllRanges();
        selection.addRange(range);
      }
    }
    
    draggedElement = null;
  });
});
Before drag

Text before

Draggable

Text after

Single draggable element
After drop (Bug)

Text before

DraggableDraggable

Text after

Element is duplicated after drag and drop
vs
✅ Expected

Text before

Draggable

Text after

Expected: Element should be moved, not duplicated

Playground for this case

Use the reported environment as a reference and record what happens in your environment while interacting with the editable area.

Reported environment
OS: Windows 10-11
Device: Desktop or Laptop Any
Browser: Firefox 120+
Keyboard: US QWERTY
Your environment
Sample HTML:
Event log
Use this log together with the case description when filing or updating an issue.
0 events
Interact with the editable area to see events here.

Comments & Discussion

Have questions, suggestions, or want to share your experience? Join the discussion below.