Scenario

Link insertion and editing behavior varies across browsers

When inserting or editing links in contenteditable elements, the behavior varies significantly across browsers. Creating links, editing link text, and removing links can result in unexpected DOM structures or lost formatting.

formatting
Scenario ID
scenario-link-insertion

Details

When inserting or editing links in contenteditable elements, the behavior varies significantly across browsers. Creating links, editing link text, and removing links can result in unexpected DOM structures or lost formatting.

Observed Behavior

  • Chrome/Edge: Creates <a> element around selected text, preserves formatting
  • Firefox: May create nested links or lose formatting
  • Safari: May create unexpected DOM structures
  • Chrome/Edge: Text editing works, but link may be lost if all text is deleted
  • Firefox: May break the link structure when editing
  • Safari: May create nested elements or lose the link
  • Chrome/Edge: May require manual DOM manipulation
  • Firefox: Behavior varies, may leave empty anchor tags
  • Safari: May create unexpected structures
  • Chrome/Edge: May create a link or paste as plain text
  • Firefox: Behavior inconsistent
  • Safari: May create nested links or lose link structure

Impact

  • Inconsistent link creation and editing experience
  • Risk of creating malformed HTML (nested links)
  • Loss of link structure when editing
  • Difficulty implementing consistent link behavior

Browser Comparison

  • Chrome/Edge: Generally better link handling, but still has edge cases
  • Firefox: More likely to create nested links or lose structure
  • Safari: Most inconsistent behavior

Workaround

Implement custom link handling:

element.addEventListener('beforeinput', (e) => {
  if (e.inputType === 'formatCreateLink') {
    e.preventDefault();
    const selection = window.getSelection();
    if (selection.rangeCount === 0) return;
    
    const range = selection.getRangeAt(0);
    const url = prompt('Enter URL:');
    
    if (url) {
      // Create link while avoiding nested links
      createLinkSafely(range, url);
    }
  }
});

function createLinkSafely(range, url) {
  // Check if selection is already in a link
  const existingLink = range.commonAncestorContainer.closest('a');
  if (existingLink) {
    // Remove existing link first
    const parent = existingLink.parentNode;
    while (existingLink.firstChild) {
      parent.insertBefore(existingLink.firstChild, existingLink);
    }
    parent.removeChild(existingLink);
  }
  
  // Create new link
  const link = document.createElement('a');
  link.href = url;
  link.textContent = range.toString();
  
  range.deleteContents();
  range.insertNode(link);
}

References

Scenario flow

Visual view of how this scenario connects to its concrete cases and environments. Nodes can be dragged and clicked.

React Flow mini map

Variants

Each row is a concrete case for this scenario, with a dedicated document and playground.

Case OS Device Browser Keyboard Status
ce-0100-link-insertion-chrome Windows 11 Desktop or Laptop Any Chrome 120.0 US draft
ce-0133-link-removal-leaves-empty Windows 11 Desktop or Laptop Any Firefox 120.0 US draft
ce-0152-link-href-update-difficult Windows 11 Desktop or Laptop Any Chrome 120.0 US draft

Browser compatibility

This matrix shows which browser and OS combinations have documented cases for this scenario. Click on a cell to view the specific case.

Confirmed
Draft
No case documented

Cases

Open a case to see the detailed description and its dedicated playground.

Related Scenarios

Other scenarios that share similar tags or category.

Tags: link, anchor, formatting

Typing adjacent to formatted elements causes unexpected behavior

When typing text next to formatted elements (links, bold, italic, etc.) in contenteditable, the input events may include the formatted element's text in event.data, selection ranges may include the formatted element, and text may be inserted into the formatted element instead of after it. This occurs across different browsers and input methods.

1 case
Tags: formatting

Code block editing behavior varies across browsers

Editing text within code blocks (<pre><code>) in contenteditable elements behaves inconsistently across browsers. Line breaks, indentation, whitespace preservation, and formatting may be handled differently, making it difficult to maintain code formatting.

4 cases
Tags: formatting

execCommand is deprecated but still widely used for formatting

The document.execCommand() API, which is commonly used to apply formatting (bold, italic, etc.) in contenteditable regions, has been deprecated. However, there is no complete replacement, and many implementations still rely on it. This creates uncertainty about future browser support.

1 case
Tags: formatting

Font family changes behave inconsistently

Changing font family in contenteditable elements behaves inconsistently across browsers. The font-family CSS property may be applied inline, as a style attribute, or may not be applied at all. The behavior also varies when editing text after applying a font.

3 cases

Comments & Discussion

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