iOS Safari does not hide the caret on non visible selections. E.g. NodeSelection

In the attached gif we can see how the caret is been showed even if the node selection is active. It only happens on real devices or emulators (Safari Desktop works fine). This is my investigation so far:

  • iOS Safari still shows the cursor even if the parent is been hidden by position: absolute; left: -10000px; strategy. Also, I tried any combination of this or to hide the element without success.
  • I tried changing the caret color to transparent, but iOS Safari does not apply the new caret color until a range selection happens.

Any other recommendations to fix this?

I haven’t found any way to properly hide the cursor in Mobile Safari, unfortunately.

Yeap, that was my conclusion too. I just want to check. :frowning:

Do you know if this is something that we should escalate to Webkit itself? Because, as far as I see, CSS behavior just work different in Mobile Safari. Not sure if it’s intended or a bug.

If you have a way to do that, that’d be awesome. But in general, they tend to not do much about contentEditable bugs reported by outsiders.

I’ve submitted this bug to the Apple Feedback Assistant and spammed a few spots in their forums. It’s so bad that you can even see it broken on the MDN page for caret-color.

We were able to get around this with an incredibly hacky solution of detecting if the selection visibility value changes via view->update in a Safari Prosemirror plugin we made. When the visibility changes, we would create a temporary input with the correct caret-color (default or transparent), mount it to the document, wait for a repaint by waiting for two requestAnimationFrames, then refocus into the editor. It somehow tricked it just enough to normally force the right caret-color. However this doesn’t work 100% of the time and throwing selection/focus around can cause bugs if you aren’t careful.

iOS contenteditable is the absolute worst.

Nice. I mean, terrible, but cool that something like that is possible.

It is.


We were finally able to solve this inside of our native app. You can set “tintColor” on the webview instance and then stop updating caret-color altogether on the CSS side. You would just need to connect Prosemirror through the webview to the native layer in iOS and then update the tintColor (it wasn’t easy).

Also just to point out the obvious, this does not help on mobile Safari and it would only work on a native app that uses a webview with Prosemirror. But if you can get all the way to the native layer, you just set webView.tintColor = [UIColor clearColor]; when the selection is not visible and the editor is focused, and then set webView.tintColor = nil; when the selection is visible or the editor is not focused.