0

The JS code is there to remove remaining newlines when h1.textContent is empty, so that :empty::before gets applied. This is a simplified version of the code I'm working on (so inclusion of "elemToDel" and its operations are required).

The problem is that pressing enter when there is no text present causes the caret to seemingly ignore the text-indent.

Code:

const h1 = document.querySelector('h1');

h1.addEventListener('input', () => {
  if (h1.textContent !== '') return;
  
  let elemToDel = [];
    
  for (let i of h1.children) {
    elemToDel.push(i);
  }

  elemToDel.forEach(i => i.remove());
});
h1 {
  border: 1px black solid;
  outline: none;
  text-indent: 36px;
}

h1:empty::before {
  content: attr(placeholder);
  color: grey;
}
<h1 placeholder="Text Here" contenteditable="true"></h1>

https://jsfiddle.net/pbmdg3ha/2/

Before pressing enter:

enter image description here

After pressing enter:

enter image description here

I wrote this:

const caretPos = window.getSelection();
const range = document.createRange();

range.selectNodeContents(h1);
range.collapse(false);

caretPos.removeAllRanges();
caretPos.addRange(range);

right after "elemToDel.forEach(i => i.remove());" to try to get the caret to go to its original position but it didn't seem to work.

I also tried:

h1.textContent = ' ';

after "elemToDel.forEach(i => i.remove());" which fixed the caret issue, but at the cost of removing the ::before.

Does anyone know of a fix or workaround?

EDIT: After some further testing, it seems that removing the :empty::before altogether fixes the issue too. At this point I'm inclined to believe that this is a bug.

2
  • What you are observing is interesting for me, if you press enter when empty and you console.log(i) it looks like as if (enter is composed of 2 div with a br inside) Commented Jan 24 at 21:56
  • @Mehdi yeah. What gets inserted isn't even consistent between browsers by the looks of it (stackoverflow.com/a/14638981/25445739) Commented Jan 25 at 8:02

1 Answer 1

0

If I understood properly you don't want the return of the enter key when there is no text in the contenteditable element. For that you can use a 'keydown' eventlistener on that element to check when the enter key is pressed (e.key=='Enter) and when the content is empty (h1.textContent.trim()=='') just use e.preventDefault().

const h1 = document.querySelector('h1');
h1.addEventListener('keydown', (e) => {
  if ( e.key =='Enter' && h1.textContent.trim()=='') e.preventDefault();
})
h1 {
    border: 1px black solid;
    outline: none;
    text-indent: 36px;
  }
  
  h1:empty::before {
    content: attr(placeholder);
    color: grey;
  }
<h1 placeholder="Text Here" contenteditable="true"></h1>

Sign up to request clarification or add additional context in comments.

1 Comment

While this avoids the caret problem, it causes the ::before to disappear when you type something, then delete it all. I've updated my question to add clarity

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.