The Mozilla HTML editor creates a bunch of <br> elements for historical reasons. One of the most irritating situations is when you expect a <p> but get a <br>… for example in this ContentEditable demo:

Go ahead, edit away!

Here's a typical paragraph element

  1. and now a list
  2. with only
  3. three items

[Return] in paragraphs

When editing a “contentEditable” element in Firefox, pressing [Return] in a paragraph splits the paragraph: if you press [Return] at the end of a paragraph, a new paragraph is created.

When editing HTML documents in comm-central apps (Thunderbird HTML messages, SeaMonkey Composer documents) the behavior is slightly different:

  • pressing [Return] once at the end of a paragraph creates a <br> element;
  • pressing [Return] twice at the end of a paragraph creates a <p> element.

The reason is, the editor component has a returnInParagraphCreatesNewParagraph property which is true by default on Firefox, but not on Thunderbird and SeaMonkey. You can set this property to false on Firefox (contentEditable) with:

 document.execCommand("insertBrOnReturn", false, "true")

Note that the insertBrOnReturn command is Mozilla-specific.

SeaMonkey and Thunderbird parse the editor.CR_creates_new_p preference (false by default) and apply its value to editor.returnInParagraphCreatesNewParagraph. You can change the value of editor.CR_creates_new_p in “about:config” if you prefer the Firefox behavior (and you probably do).

A trickier case in Firefox is when the active editing host is an inline element:

Try to press [Return] here and complain.

 <p> Try to
     <span contenteditable>press [Return] here</span>
 and complain. </p>

As Firefox always tries to create a new paragraph in such situations, and since the editing host is a <span>, nothing happens when [Return] is pressed. This should be fixed with bug 460740.

Of course, in all cases a [Shift+Return] creates a <br>, which is fine.

[Return] in headers and lists

With current versions of Firefox (5, Beta, Aurora):

  • pressing [Return] at the end of a header element (<h[1…6]>) creates two line breaks (<br>), though most users expect a new paragraph.
  • pressing [Return] once at the end of a list element (<li> or <dt>) creates a new list item (<li> or <dd> respectively); pressing [Return] twice splits the list if necessary and creates a line break, though again, most users expect a new paragraph.

Note that there’s no equivalent to the editor.returnInParagraphCreatesNewParagraph property for headers or lists: pressing [Return] at the end of list or header element never inserts any <br> within this element.

There’s no spec that describe the expected behavior of the HTML editor in such case. I think the only intuitive rule would be to create a new block element (<p>) when we’re getting out of another block element with [Return]. That’s what Chromium and Opera do (and probably IE and Safari as well), and that’s what I’ve done in bug 449243. You can test this behavior in Firefox Nightly.

Note: when editing a list in Thunderbird or SeaMonkey Composer with this patch, if you click on the “list” toolbar button the list content will be converted to body text, not to a paragraph. I’ll have to work on that in order to preserve the consistency.

Consistency: <p> everywhere?

Again, there’s no spec for the behavior of the [Return] key in an editable document fragment but we can assume that the [Return] key action should be as consistent as possible across the different editing situations. That’s the idea behind the new behavior of the [Return] key in headers and lists.

I don’t think the editor should force all text to be enclosed in paragraphs, though. As an example, in this editable <div> there’s no HTML structure so I expect [Return] to create <br>:

Type your text here!
 <div contenteditable>
     Type your text here!
 </div>

When [Return] is pressed at the end of the line of text, I expect to get a <br> (FWIW, that’s what Chromium does, too). I don’t expect [Return] to turn the text into a paragraph, then create another paragraph. If I wanted all text to be enclosed in paragraphs I could just use this instead:

Type your text here!

 <div contenteditable>
   <p> Type your text here! </p>
 </div>

I think comm-central apps (Thunderbird, SeaMonkey…) might want to adapt to this new behavior: since HTML messages in Thunderbird and documents in SeaMonkey Composer are structured HTML documents, these apps could initialize the editor not on “about:blank” as they do now, but on an empty HTML document containing a paragraph. In this case, changing the default value of editor.CR_creates_new_p would make sense.

I’m pretty sure that’s what SeaMonkey Composer users want, but I don’t know if this applies to Thunderbird. In fact, Thunderbird might even prefer creating <br> instead of <p> when [Return] is pressed… if that’s the case, please let me know.

[update 2011-07-28] Aryeh Gregor (WhatWG) has just published a preliminary draft of the HTML Editing APIs specification. Thanks Anthony for the link!