Phenomenon
When a user presses the Enter key in a contenteditable container, Chromium-based browsers (Chrome, Edge) sometimes insert two <br> elements instead of one. This behavior typically occurs when the browser attempts to ensure the new line is “visible” or when it mismanages the “default paragraph separator”. This leads to a “double-spacing” effect that is difficult to manage in custom editors.
Reproduction example
- Create a
contenteditablediv with no initial content or a single line of text. - Type some text (e.g., “Hello”).
- Press the
Enterkey. - Inspect the DOM. In many cases, you will see
Hello<br><br>if the editor is in a state that forces<br>usage.
Observed behavior
- Double
Insertion: A singlekeydownfor Enter results in two<br>tags being appended. - Mix of Div/Br: Depending on the
defaultParagraphSeparatorsetting, Chrome might wrap lines in<div>but still insert a<br>inside or between them, leading to inconsistent vertical spacing. - Platform Specificity: This is particularly prevalent on macOS and Linux, where the default system line-ending expectations might conflict with Chrome’s internal DOM conversion logic.
Expected behavior
- Pressing Enter should insert exactly one logical line break.
- If
document.execCommand('defaultParagraphSeparator', false, 'p')or'div'is set, it should consistently wrap the new block without stray<br>elements causing extra height. - The visual result should match standard word processor behavior (single spacing unless specifically configured otherwise).
Solution and Workarounds
- Manual Enter Handling:
- Intercept the
keydownevent for Enter (keyCode 13). - Use
event.preventDefault()to stop the browser’s default insertion. - Programmatically insert a single
<br>usingdocument.execCommand('insertHTML', false, '<br>')or by manually manipulating the text nodes and selection.
- Intercept the
- Default Paragraph Separator:
- Set
document.execCommand('defaultParagraphSeparator', false, 'p')globally when the editor initializes. This encourages Chrome to use<p>tags for new lines, which is generally more stable than raw<br>tags.
- Set
- Trailing Br Management:
- Some editors maintain a “padding”
<br>at the end of every block to ensure the height is rendered correctly even if the block is empty. Ensure your logic accounts for this “magic”<br>so it doesn’t get duplicated.
- Some editors maintain a “padding”