Contenteditable element's cursor doesn't go back to original place when inserting new line and deleting

Viewed 56

I have this simple html code:

span{
  outline: none;
}
hello
<span contenteditable="true">
  world
</span>

And I noticed that every time I press ENTER in the contenteditable span, the cursor goes to a new line as expected, but when pressing backspace the cursor doesn't go to it's original place, it moves more to the left + up, and only when pressing backspace again, it goes to the original place:

enter image description here

Is this a bug? Are there any workarounds?
Thanks

2 Answers

When using the Chrome debugger you will notice that upon pressing enter there are two line breaks generated within the span. As you noticed only when pressing backspace for the second time you delete the second linebreak which probably is the reason for the spacing irregularity you're expiriencing.

As far as i know this is normal since line breaks interact with whitespace in some way

Edit: I spent quite some time playing around with this and it turns out contrary to what you assumed there are three positions for the coursor:

  1. With text present in the contenteditable span the coursor aligns with its content box
  2. Without text and a line break present after it the coursor aligns with the previous text
  3. Without text nor a line break the coursor sits slightly below the content box of your span for some peculiar reason.

Why all this happens, sadly i have no idea but hopefully you can use this information to your advantage

Edit 2: Found out where the coursor goes in the 3rd case namely it snaps to the bottom of the parents content box in your case that would be the body element

Here's the bit of code I made for you to see that for yourself:

span[contenteditable="true"] {
        outline: none;
        background-color: red;
        border: 2px solid blue;
        line-height: 2em;
      }
      span.first {
        font-size: 0.8em;
        border:2px solid violet
      }
      br{
        border: 2px solid green;
      }
      body {
        font-size: 10rem;
        border: 2px solid aqua
      }
<!DOCTYPE html>
<html>
  <body>
    <span class="first">
      hello
    </span>
    <span contenteditable="true"> world </span>
</html>

Finally, I have managed to trick the browser using ZeroWidthSpace character which always being inserted to the start of the element's innerHTML. As far as I understand, the bug(?) only occurs if there is no text in the element so inserting a 'non-text' character solved it.

Here's a snippet I made using custom Web Component that automatically fixes the problem:

class CeElement extends HTMLElement {
  class CeElement extends HTMLElement {
        constructor() {
            super();
        }
        connectedCallback(){
            this.addEventListener("input", function() {
                if(!this.innerHTML || this.innerHTML==0) {
                    this.innerHTML = "&#8203;";
                }
            }, false);
            this.innerHTML = "&#8203;" + this.innerHTML;
            this.contentEditable = true; 
        }
}
window.customElements.define('ce-element', CeElement);
ce-element{
  outline: none;
}
<span style="white-space: pre;">hello </span>  <! -- the span is only for the saving the space with 'white-space: pre;' -->
<ce-element>
world
</ce-element>

Related