Chrome 中内联元素的插入符号位置和选择高度

mow*_*ker 8 html css contenteditable prose-mirror slatejs

我正在考虑使用SlateProseMirror构建一个编辑器,并在使用内联元素时在插入符号位置和选择区域周围看到 Chrome 的一些奇怪行为。问题 1 显示在下面的第一张图片中。当文本光标位置在“f”后面时,插入符号显示在图像的顶部。问题 2 在第二张图片中 - 选择文本会显示一个与内联元素一样高的突出显示区域。有什么方法可以控制这种行为,而是在文本位置显示插入符号,并且只突出显示文本周围的空间(即使内嵌图像使行高变大) 插入符号位置太高 选择区域太大

我想模仿这里的行为,来自 Firefox: 在此处输入图片说明 在此处输入图片说明

示例图像是使用此处的 ProseMirror 演示生成的:https ://prosemirror.net/examples/basic/

JSBin 的最小示例(感谢@Kaiido):

<div contenteditable>Test text<img src="https://upload.wikimedia.org/wikipedia/en/9/9b/Yoda_Empire_Strikes_Back.png">Testing</div>

Run Code Online (Sandbox Code Playgroud)

不确定这在其他操作系统上的表现如何,但我使用的是 macOS Catalina。

wiz*_*zeb 4

您可以使用 Flexbox 解决选择问题。我最初尝试使用,align-items: flex-end但我得到了一些奇怪的箭头键行为。align-items: baseline目前看来有效。

图像问题很奇怪。我注意到 Chrome 对 SVG 元素的处理方式与 IMG 元素不同。截至目前,最新版本的 Chrome 在跳过 IMG 之前会“等待”,但允许用户像任何其他字符一样跳过 SVG(左箭头跳过最接近 svg 的字符)。这可能是由底层默认样式引起的,但我不知道。

我正要发布我的发现,但我意识到 Firefox 的工作方式不一样。当使用 SVG 和/或 Flexbox 时,Firefox 有一些非常奇怪的箭头键行为。光标会移至图像上方,但仅当按向右箭头键时才会出现。

然而,Firefox 可以很好地处理普通的 IMG 元素。

长话短说,您将必须根据浏览器渲染不同的图像元素。

// chrome contenteditable ads spaces between spans.
// firefox does not, so you have to add them manually.
if (navigator.userAgent.indexOf("Firefox") > 0) {
  Array.from(document.querySelectorAll('#editable span')).forEach(el => {
    el.innerHTML += " "
  })
}
Run Code Online (Sandbox Code Playgroud)
.flexit {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
}

span {
 display: inline-block;
 white-space: pre;
}

.img-wrapper, .img-wrapper + span {
display: inline;
}
Run Code Online (Sandbox Code Playgroud)
<!DOCTYPE html>
<html>

<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>JS Bin</title>
</head>

<body>
  <h1>chrome</h1>
  <div contenteditable="true" class="flexit">
    <span>test</span><svg width="200" height="200" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">       
  <image href="https://mdn.mozillademos.org/files/6457/mdn_logo_only_color.png" height="200" width="200"/>
    </svg><span>Here</span><span>is</span><span>a</span><span>longer</span><span>sentence.</span><span>Notice</span><span>I</span><span>wrapped</span><span>each</span><span>word</span><span>in</span><span>a</span><span>span.</span><span>This</span><span>makes</span><span>the</span><span>text</span><span>appear</span><span>like</span><span>it</span><span>is</span><span>inline.</span>
  </div>

  <h1>firefox</h1>
  <div contenteditable="true" id="editable">
    <span>test</span><span class="img-wrapper"><img src="https://mdn.mozillademos.org/files/6457/mdn_logo_only_color.png" height="200" width="200" /></span><span>test</span><span>Here</span><span>is</span><span>a</span><span>longer</span><span>sentence.</span><span>Notice</span><span>I</span><span>wrapped</span><span>each</span><span>word</span><span>in</span><span>a</span><span>span.</span><span>This</span><span>makes</span><span>the</span><span>text</span><span>appear</span><span>like</span><span>it</span><span>is</span><span>inline.</span>


  </div>
</body>

</html>
Run Code Online (Sandbox Code Playgroud)

PS 很多编辑器我都使用默认的全角图像。

编辑:我刚刚意识到我的 Firefox 解决方案似乎也适用于最新的 Chrome。我认为这是可行的,因为我将文本节点包装在 SPAN 元素中。SVG 元素在 Chrome 中的工作方式仍然不同,但在 SPAN 中换行文本似乎解决了大部分问题。