2

I created a div tag with the contenteditable attribute. I want to put the placeholder in here, and I found the following code.

[contenteditable=true]:empty:before {
  content: attr(placeholder);
  display: block;
  /* For Firefox */
}
<div class="test" contenteditable="true" placeholder="test"></div>

In a chromium-based engine, it looks like it's working. But I heard there is an error here that requires JavaScript. I couldn't find the error. Can you tell me what the problem is?

I'm also not sure that content:attr(); is the web standard in css. Is it a standardized CSS property?

Richard
  • 7,037
  • 2
  • 23
  • 76
eujin
  • 172
  • 2
  • 12

3 Answers3

2

The problem is that a <br> is automatically inserted inside a contenteditable div when it is empty. I think that they added <br> to prevent it from collapsing. Here's where they discussed this: Bugzilla.

Here's an example of the collapse prevention I mentioned. You can see that, initially, div has 0 height. However, you can still focus on it. Try typing, then erasing everything. Browser automatically inserts <br> to prevent it from returning to 0 height by adding a <br> which is one line-height high.

div {
  border: 1px solid black;
}
<div contenteditable="true" data-placeholder="Test"></div>

So we can simply use <span>, which does not insert a random <br>, instead of <div> to do what you want like so. Try typing, then erasing the characters. The placeholder will be there exactly as you want it to be.

* {
  box-sizing: border-box;
}

span {
  display: block;
  width: 100%;
  border: 1px solid black;
  border-radius: 5px;
  font-family: sans-serif;
  padding: 10px;
  cursor: text;
}

span:empty::before {
  content: attr(data-placeholder);
  display: block;
  height: 100%;
  color: #00000066;
}
<span contenteditable="true" data-placeholder="Test"></span>

If you really have to use div, then you can erase the <br> manually using JS:

const editable = document.querySelector('#editable')
editable.addEventListener('keyup', e => {
  if (editable.innerText === '\n') editable.innerHTML = ''
})
* {
  box-sizing: border-box;
}

#editable {
  display: block;
  width: 100%;
  border: 1px solid black;
  border-radius: 5px;
  font-family: sans-serif;
  padding: 10px;
  cursor: text;
}

div:empty::before {
  content: attr(data-placeholder);
  display: block;
  height: 100%;
  color: #00000066;
}
<div id="editable" contenteditable="true" data-placeholder="Test"></div>

Using attr() function in CSS with content is not experimental. With other CSS properties like color, though, it is still experimental. Read further on this MDN page.

Richard
  • 7,037
  • 2
  • 23
  • 76
2

In .html

<div placeholder="Write your message.." contenteditable class="form-control edit-box holder"></div>

In .css

.holder:before {
    content: attr(placeholder);
    color: lightgray;
    display: block;
    position:absolute;    
    font-family: "Campton", sans-serif;
}

This solution worked for me.

Sahil Ralkar
  • 2,331
  • 23
  • 25
0

It works on Firefox too. I think I found the "error" that may require the supposed Javascript. Try typing in the div, then delete all of it by CTRL+A backspace; the placeholder won't come back because there's a <br> the browser has automatically inserted (<p></p> in other browsers).

The content property and attr(...) has been standard since IE8, so it's fine.

Jonathan Rosa
  • 992
  • 7
  • 22
  • I found the answer you copied on the link. It looks like all of the CSS-only solutions has this issue. Answer #2 at the link (which is CSS only) has a comment that says `this fails and is unreliable`. So try out the first solution (even if it looks ugly). – Jonathan Rosa Mar 02 '20 at 02:32
  • Now I finally found what to do. Thank you very much. – eujin Mar 02 '20 at 02:49
  • @Jon.Frenchtoast The first solution has a problem too. Try focusing on the div, then direct the focus elsewhere. The placeholder will be missing. – Richard Mar 02 '20 at 02:53
  • @Richard I found out it doesn't even work when you actually type something and then refocus on it, it deletes it. I don't think any of the solutions there work *exactly* like how the `placeholder` attribute is specified in HTML5. – Jonathan Rosa Mar 02 '20 at 03:00
  • Thank you for your sound discussion. When I clicked somewhere else, I noticed the problem of the focus. What do you think of this link? [link](https://stackoverflow.com/questions/20726174/placeholder-for-contenteditable-div) , [link](https://stackoverflow.com/questions/9093424/placeholder-in-contenteditable-focus-event-issue) – eujin Mar 02 '20 at 04:56