3

When a contenteditable element has position: relative and a background color, the caret is invisible when it's placed in that element. Here's an example:

.bug {
  position: relative;
  background-color: lightgrey;
}
<div contenteditable>
  This has caret
  <span class="bug">no caret here?!</span>
  this has caret
</div>

My first thought was "this is a browser bug", but it's the exact same bug on Chrome and Firefox!

What causes the caret to disappear? And is there a workaround?

jameshfisher
  • 34,029
  • 31
  • 121
  • 167
  • 1
    Wow, it's kind of awesome there is a full browsers consensus on such a weird behavior, moreover in this interop' hell that is `contenteditable`, one of the rare spots implementations do agree on... (seeing you do develop for macOS, I should note I only tested on macOS, maybe it's OS dependent). – Kaiido Jan 03 '22 at 12:22
  • 1
    Just found this reported as a Chromium bug: https://bugs.chromium.org/p/chromium/issues/detail?id=806904 – jameshfisher Jan 03 '22 at 14:23
  • It's also reported for Webkit: https://bugzilla.mozilla.org/show_bug.cgi?id=1748239 – jameshfisher Jan 03 '22 at 15:00
  • I just reported it for Firefox: https://bugzilla.mozilla.org/show_bug.cgi?id=1748239 – jameshfisher Jan 03 '22 at 15:00

1 Answers1

6

Don't know the exact cause of the issue but you can fix it in multiple ways.

My previous explanation (maybe wrong) :

This isn't a bug, you put the background color on a <span> tag (in position:relative) inside a contenteditable div element and so the span is on top of the contenteditable div.

I still think is related to the z-index since we can see on the image below the red background on top of the Chrome focus border:

enter image description here

Remove position:relative

Removing position:relative of the <span> fix the issue:

.no-bug {
  background-color: red;
}
<div contenteditable>
  This has caret
  <span class="no-bug">This has caret !</span>
  this has caret
</div>

Adding a z-index to the <span> element

Adding a negative z-index also fix the issue:

.no-bug {
  background-color: red;
  position: relative;
  z-index: -10;
}
<div contenteditable>
  This has caret
  <span class="no-bug">This has caret !</span>
  this has caret
</div>

Adding a display: inline-block to the <span> element

Adding a display: inline-block (or display: block) fix the issue:

.no-bug {
  background-color: red;
  position: relative;
  display: inline-block;
}
<div contenteditable>
  This has caret
  <span class="no-bug">This has caret !</span>
  this has caret
</div>

Others Stackoverflow related questions

Ben Souchet
  • 1,450
  • 6
  • 20
  • But the span also has its own `.isContentEditable` set to `true`. The caret is inside that span element, as you can check using the Selection API, it should logically be over this element's background. – Kaiido Jan 03 '22 at 12:19
  • @Kaiido this is true, I answer was incorrect, I updated my answer with ways to fix the issue but don't know exactly what is the origin of the issue. – Ben Souchet Jan 03 '22 at 13:05
  • 1
    Thanks @BenSouchet - `z-index: -1` fixes the issue for me! `display: inline-block` is not an option for me due to [a different browser bug](https://bugs.chromium.org/p/chromium/issues/detail?id=1088403). What a bizarre issue! I think I'll report this as a browser bug anyway ... – jameshfisher Jan 03 '22 at 14:08