[whatwg] Should editable elements have placeholder attribute?

Jussi Kalliokoski jussi.kalliokoski at gmail.com
Thu Aug 30 01:43:40 PDT 2012

It's pretty simple to make a naive placeholder for contenteditable elements
with CSS:

[contenteditable]:not(:focus):empty::after {
        content: attr(data-placeholder);
        color: #ccc;

I call it a bit naive because it turns out that if you have insert a line
break in the box, there will always be one line break inside the element
(even if you clean it empty), making the element non-empty and hence the
placeholder won't show.

You can try it in action here:


P.S. The trick is courtesy of my colleague Nick Markwell (
https://duckinator.net/ ) so if you want to thank someone for it, thank him.

On Thu, Aug 30, 2012 at 2:27 AM, Ian Hickson <ian at hixie.ch> wrote:

> On Sun, 17 Jun 2012, Aryeh Gregor wrote:
> > On Thu, Jun 14, 2012 at 1:11 AM, Ian Hickson <ian at hixie.ch> wrote:
> > > I strongly disagree. <input> and <textarea> are high-level constructs,
> > > so it's fine for them to be defined by the UA's platform. But
> > > contenteditable is a very low-level primitive. We can't just punt on
> > > how it interacts with CSS; otherwise people will have no way to
> > > reliably make UIs with it.
> >
> > I don't know why you think contenteditable is "lower-level" than
> > input/textarea.
> By "high level" I mean something that is self-contained, usable as a
> standalone feature, which typically integrates with other features in an
> atomic fashion; "lower-level", then, means something that in comparison
> requires more work to use, can only be used in conjunction with something
> else, etc. By analogy, a fruit juice box is high-level: it comes with its
> own straw, it doesn't need any additional tools to open it, it provides a
> final product without requiring any additional work. On the other hand, a
> can of frozen grape concentrate requires a bowl in which to mix the
> concentrate and some water, a spoon to stir them together, a jug from
> which to pour the result, a glass in which to pour it and from which to
> drink the resulting fruit juice.
> <input type=text> is a high-level construct: it provides a self-contained
> place in which text can be entered, it plugs straight into the form
> submission system, it exposes hooks for setting the value or retrieving
> the user's input that do not require knowing how the control works.
> contenteditable="", on the other hand, exposes the DOM directly, has no
> integration with other features like form submission, has a much less
> obvious boundary between it and surrounding content... if you want to use
> it in real content, there's no way to do it without script of some kind,
> and if you want to use it to do anything especially compelling, you need a
> lot of script (to provide all the UI for formatting, etc).
> This isn't a criticism of contenteditable="". Low-level primitives are the
> building blocks of platforms. But it does mean that we have different
> tradeoffs to make in the designs of the features.
> > >> In the end this is the check that I'm using at the moment (I didn't
> > >> perform extensive tests, just enough to check that it seemed to work)
> > >>
> > >> var value = data.replace( /[\n|\t]*/g, '' ).toLowerCase();
> > >> if ( !value || value == '<br>' || value == '<p> <br></p>' ||
> value ==
> > >> '<p><br></p>' || value == '<p> </p>' )
> > >>     return true;
> > >
> > > Now there's a problem we should fix. Having five different
> representations
> > > of "nothing" seems like a terrible position for us to be in.
> >
> > If you type some stuff and then delete it all, the desired result will
> > vary based on lots of factors, e.g.:
> >
> > * Whether <div> or <p> is being used for paragraph separators.  Both
> > <p><br></p> and <div><br></div> might make sense for "nothing",
> > depending.  This is author-configurable using the
> > defaultParagraphSeparator command.
> >
> > * Whether there was any styling present before.  If all the text was
> > previously bold, for instance, deleting everything might result in
> > something like <p><b><br></b></p>, because per spec, deletion doesn't
> > remove style tags from empty lines.
> >
> > * Whether there was any other special markup.  If something (like
> > execCommand("insertHTML")) made the first line have <p id="foo">, then
> > deleting everything would result in <p id="foo"><br></p>.
> >
> > * What the author specified as the initial contents of the editable
> > area.  If you have <div contenteditable><br></div> to start with, and
> > the user puts the cursor there and then types "foo" and then deletes
> > it, you'll go back to having just <br>, because nothing ever inserted
> > a <p> or <div> or anything.  (As soon as the user hits Enter, both the
> > old and new lines are wrapped in a paragraph separator per spec,
> > although only IE/Opera do this right now.)
> >
> > Really, you can have any HTML markup at all in contenteditable, and we
> > can't avoid that.  There's not going to be any reliable way to figure
> > out what "nothing" is if you can't answer the same question for
> > arbitrary HTML.
> Maybe the right way to detect "nothing" is to compare textContent against
> "" and then to look for specific elements that count as palpable content,
> like <img>. Would it make sense to provide an API for that?
> --
> Ian Hickson               U+1047E                )\._.,--....,'``.    fL
> http://ln.hixie.ch/       U+263A                /,   _.. \   _\  ;`._ ,.
> Things that are impossible just take longer.   `._.-(,_..'--(,_..'`-.;.'

More information about the whatwg mailing list