Case ce-0170-code-block-indentation-lost · Scenario scenario-code-block-indentation-lost

Code block loses indentation when typing in contenteditable pre tag

OS: Any Any Device: Desktop or Laptop Any Browser: Chrome Latest Keyboard: US Status: draft
code-block pre indentation whitespace

Phenomenon

When using a <pre> tag with the contenteditable attribute to create an editable code block, pressing Enter often inserts <br> tags instead of preserving newline characters (\n). This behavior disrupts the intended formatting of code, and indentation may be lost when users type.

Reproduction example

  1. Create a <pre contenteditable="true"> element with code content.
  2. Place cursor in the middle of a line.
  3. Press Enter to create a new line.
  4. Inspect the HTML to see if <br> tags were inserted.
  5. Type code with indentation and observe if indentation is preserved.

Observed behavior

  • Enter key: Inserts <br> tags instead of newline characters.
  • Indentation lost: Whitespace and indentation may not be preserved.
  • Wrapping elements: Some browsers may wrap new lines in <div> or <p> tags.
  • Formatting disruption: Code formatting is broken by unexpected HTML structure.
  • Whitespace collapse: Multiple spaces may be collapsed into single spaces.

Expected behavior

  • Pressing Enter should insert newline characters (\n), not <br> tags.
  • Indentation should be preserved when typing.
  • Whitespace should be maintained as entered.
  • Code formatting should remain intact.

Analysis

Browsers treat contenteditable <pre> elements similarly to other contenteditable elements, applying HTML formatting rules that don’t preserve code-specific formatting. The browser’s default Enter behavior inserts HTML elements rather than preserving plain text newlines.

Workarounds

  • Intercept Enter key to insert newline character:
    preElement.addEventListener('keydown', (e) => {
      if (e.key === 'Enter') {
        e.preventDefault();
        document.execCommand('insertText', false, '\n');
      }
    });
  • Sanitize content after input to replace <br> with \n:
    function sanitizePreContent(preElement) {
      let content = preElement.innerHTML;
      content = content.replace(/<br>/g, '\n');
      content = content.replace(/<\/?div>/g, '');
      preElement.textContent = content;
    }
  • Use white-space: pre-wrap; CSS to preserve whitespace.
  • Consider alternative approaches like overlaying syntax-highlighted <pre> over hidden <textarea>.

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: Any Any
Device: Desktop or Laptop Any
Browser: Chrome Latest
Keyboard: US
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.