[whatwg] Pressing Enter in contenteditable: <p> or <br> or <div>?

Aryeh Gregor Simetrical+w3c at gmail.com
Fri May 13 10:26:23 PDT 2011


On Thu, May 12, 2011 at 4:51 PM, Boris Zbarsky <bzbarsky at mit.edu> wrote:
> It's used when serializing: things with _moz_dirty are prettyprinted even if
> the serialization is trying to preserve the original whitespace layout of
> the HTML in general.
>
> The fact that it's an actual content attribute is a bug dating back to when
> there was no other good way to associate state to an element in Gecko; we
> just need to fix that.  See
> https://bugzilla.mozilla.org/show_bug.cgi?id=459212

So it's an attribute that affects serialization in a nonstandard way?
What sort of serialization does it affect?  I just tested innerHTML,
and I found it stripped the attribute, but it didn't seem to add any
whitespace around <br>, <ol>, or <li>.

If you're going to add pretty-printing, doesn't it make more sense to
just add the text nodes directly to the DOM?  You're going to have to
deal with the extra nodes anyway as soon as the content round-trips to
a server.

On Thu, May 12, 2011 at 6:30 PM, Ehsan Akhgari <ehsan at mozilla.com> wrote:
> But it also has the semantic property of being a paragraph, which is an advantage I think.

Only if the user intends it to be a paragraph.  Usually they'll intend
that, but you don't know.  <p> is semantically inappropriate for
marking up the lines of a poem or address, for instance.

> There is also one more question to answer.  If we're already in a block level element, what should happen when pressing Enter?  For example, for <div class="foo">bar|</div>, what should happen after pressing enter?  I think the sane thing to do is to create <div class="foo">bar</div><div class="foo">|</div> (since the div might be styled on the page, and not preserving the block's tag or class attr would take that away.

I've avoided splitting elements whenever possible, because it's a
minefield.  What if it were <div id=foo>?  What if it were <div
class=foo> but the class applied some styles like borders that you'd
change if you duplicated it?  What if it were <div data-foo=bar>?
What if there was a script handler attached to the element?  Sometimes
you have to do it anyway, but I don't unless there's no other way.

In this case, I'd say it should become <div
class="foo">bar<br>|</div>, or <div class="foo">bar<div>|</div></div>,
or <div class="foo">bar<p>|</p></div>, as the case may be.

> Would you elaborate, please?  Specifically, are you saying that in it's inferior to <div> in this regard?

Yes, much inferior.  <div> can contain any block elements.  <p> cannot
contain almost anything else: <div>, <ol>, <ul>, <dl>, <p>,
<blockquote>, etc., etc. cannot be put inside it at any nesting level.
 So there's a greater risk of bugs.  For instance:

* If you give the input <p>[foo]</p> to Chrome 12 dev and run
insertOrderedList, it produces the DOM (expressed in XML)
<p><ol><li>[foo]<br /></li></ol></p>, which when you serialize to
text/html and unserialize becomes <p></p><ol><li>[foo]<br
/></li></ol><p></p>.
* If you give <p>[foo]</p> to Opera 11.10 and run indent, it produces
<p><blockquote>[foo]</blockquote></p>, which becomes
<p></p><blockquote>[foo]</blockquote><p></p> after round-tripping
through text/html.
* If you give <ol><li><div>[foo]</div>bar</li></ol> to IE9 and run
"outdent", you get <p><div>[foo]</div>bar</p>, which round-trips to
<p></p><div>[foo]</div>bar<p></p>.  (I didn't find a simpler scenario
where it produced such DOMs, to its credit.)

My algorithms contain bugs like this too, which I try to fix as I find
them.  I didn't find any in Firefox yet, I don't think, but it would
be hard to avoid them across the board.  Of course we want to behave
correctly even if there are <p>s in the input for whatever reason, but
not producing <p>s ourselves would at least mitigate the impact of
such bugs.

> br is considered to be the standard way of representing line breaks, which are part of the content.  About the problems that you're mentioning, I think we need to address them anyways, since <br>s might already be in the content even without having them assigned to Shift+Enter.

Yeah, I guess so, unless we normalized aggressively.

> I think we want to keep using <br>s, but I'm not convinced if <div> is a better choice than <p>.

I'm not completely decided at this point, but am now leaning toward
<br>.  Currently my spec uses <br> where some type of break is needed
(e.g., de-indenting an inline node when that would make it the sibling
of some other inline node), because that's the shortest markup in
simple cases.

On Fri, May 13, 2011 at 3:11 AM, Simon Pieters <simonp at opera.com> wrote:
> On Thu, 12 May 2011 22:28:47 +0200, Aryeh Gregor <Simetrical+w3c at gmail.com>
> wrote:
>> * IE9 wraps all lines in <p> (including if you start typing in an
>> empty text box).
>
> Can't reproduce. If I start typing in an empty <body contenteditable>,
> there's no <p> until I hit enter.

Yes, but when you hit Enter it wraps the first line in a <p> too, not
just the second line.  In WebKit it only wraps the second line in a
div.

> It doesn't render the same. Empty <p>s should be collapsed per CSS. (Dunno
> what IE does.)

Peculiar.  An empty <p> will leave a blank line equal to the height of
its top or bottom margin, whichever is greater, but only one, even if
you have multiple <p>s in a row.  But when I hit Enter a few times in
IE9 in a contenteditable div, I get multiple consecutive <p>s whose
margins don't collapse, but which are definitely empty in the DOM --
IE's F12 tools, Live DOM Viewer's DOM view, and manually checking
childNodes.length in the console all show no children.  When I check
innerHTML, though, it sticks in  's.

It never even occurred to me that browsers would be doing all this
voodoo magic with serialization -- at this rate I'm going to have to
do my own serialization to find out what browsers are really doing.
Do WebKit and/or Opera also do magic serialization?

> Opera 11.10 has introduced
> document.execCommand('opera-defaultblock','','div') to switch to using
> <div>s instead of <p>s. ('p' is also allowed to switch back.) Apparently
> WebKit considers implementing this as well.
> https://bugs.webkit.org/show_bug.cgi?id=59961

Kind of like styleWithCss -- instead of converging in default
behavior, just make it an option that you have to set to get the same
behavior.  Well, better than nothing, I guess.  But for actual
standardization, we still need to pick a default.

On Fri, May 13, 2011 at 6:00 AM, Michael A. Puls II
<shadow2531 at gmail.com> wrote:
> If the default content (innerHTML more or less) of the contentEditable
> element is <div><br></div> (like in
> <http://shadow2531.com/opera/testcases/designmode/000.html>), Opera will use
> DIVs when pressing enter (and <br> when pressing shift + enter).

It seems like WebKit also changes its line breaks contextually.  This
seems like it's incredibly confusing -- sometimes hitting Enter will
look like it outputs two lines, sometimes one, in the exact same text
box, depending on whether you were in a p or div.

> Ideally, users should realize that it's an editable part of a web page and
> that pressing ENTER once closes the current paragraph and starts a new one.
> They should also realize that the margins are part of the paragraphs, which
> causes them to be visually separated from other elements and that they don't
> need to do that manually by pressing ENTER again. These are not textareas or
> plain text editors after all.

Hitting Enter once normally inserts one line break in rich-text
editors too (although apparently not in Word 2007).  We are not
dealing with ideal users here, we're dealing with real users.  What we
want them to expect is not the point, all that matters is what they
actually expect.

>> Another problem with <p> is that it's very easy to create
>> unserializable DOMs with it.  I've seen cases where at least some
>> browsers will put things inside <p> that will break out of the <p>,
>> and I've done it myself by mistake too.
>
> I think the browser/editor just shouldn't allow that in this case. (Not
> saying that it's easy to enforce it though.)

We shouldn't, but no need to make the inevitable bugs have higher
impact than necessary.

> So, if I type "Line 1" and press ENTER twice and then type "Line 3", I'd
> get:
>
> <div>Line 1<br><br></div>
> <div>Line 3</div>
>
> ?

I was thinking more like <div>Line 1</div><br><div>Line 3</div>.


Anyway, at this point I'm against <p> because of the margin and
serializability issues, and undecided between <br> and <div>.  <br> is
harder to deal with, but we have to deal with it regardless, and it's
both logical and succinct.  <div> is closer to what most browsers
output by default (wrapping elements instead of using <br>), but it
adds more clutter, and all browsers do output <br> by default in some
cases.  I guess I'm leaning toward using <br> by default.  If any
implementers feel strongly, now would be a good time to speak up.


More information about the whatwg mailing list