I've just noticed that div contenteditable
in reports 1 newline as 2 newlines in Firefox.
Is this a bug or am I missing something?
In the following example just type:
Hello
World
in the contenteditable
.
Grabbing the value using innerText
reports it as:
Hello
World
const textarea = document.querySelector('#textarea')
textarea.addEventListener('keydown', e => {
console.log(textarea.innerText)
})
#textarea {
width: 200px;
height: 75px;
outline: 1px solid black;
}
<div id="textarea" contenteditable="true"></div>
This appears to be a bug with Firefox's implementation of innerText.
New lines in contenteditable
historically had a lack of consensus on the precise implementation. Gecko inserted <br>
s, IE and Opera's Presto wrapped the line in <p>
tags, and Webkit and Blink wrapped the line in <div>
tags. With its old implementation that used <br>
tags, Firefox's innerText
worked just fine, exactly how your question wants it to.
However today's modern browsers have reached a general consensus for the sake of consistency. Specifically for Firefox, MDN stated:
As of Firefox 60, Firefox will be updated to wrap the separate lines in
<div>
elements, matching the behavior of Chrome, modern Opera, Edge, and Safari.
When modern browsers insert an empty new line, they do so by wrapping a <br>
in <div>
tags. It seems that Firefox's innerText
implementation is interpreting this as two new lines.
A workaround is quite simple. The execCommand
method (unofficial W3 draft but supported by Firefox which is all we need) allows you to manipulate a contenteditable
's content with defined commands. One such command is defaultParagraphSeparator
, which allows you to specify whether to use <div>
or <p>
as the container for lines in your contenteditable
.
Firefox - and only Firefox - has additionally implemented support for <br>
s with defaultParagraphSeparator
. With this command the contenteditable behaves like it would have prior to FF60, that is, inserting line breaks instead of wrapping lines within a container.
Thus, all you need to do is put:
document.execCommand("defaultParagraphSeparator", false, "br");
in your JavaScript. All versions of Firefox will then be using <br>
s instead of containers for new lines in contenteditable
, thus making innerText
correctly interpret new lines. And every browser other than Firefox will ignore it.