如何在 contenteditable HTML 元素中的两个字符之间插入零宽度线

How to insert a zero-width line between two characters in a contenteditable HTML element

我正在使用 React 创建一个网络应用程序来帮助人们正确拼写外语单词。我想就单词拼写错误的位置提供反馈。特别是,当用户遗漏了一个字母时,我想显示一个红色标记以指示丢失的字母应该去哪里。

理想情况下,这将是一个高的单像素线或一个零宽度的插入符号,位于两个相邻字母之间。例如:

miss|ng
miss‸ng

请注意,在我上面的表示中,线条和插入符号实际上有宽度,但这正是我想要避免的。如果用户输入...

missng

... 然后我希望字母以完全相同的间距出现,并将我的红色 "you missed a letter" 字符放在 "s" 和 "n" 之间,而不移动 "n" 完全靠右。

我曾尝试使用零宽度 SPACE (U+200B),然后使用 COMBINING CIRCUMFLEX ACCENT BELOW (U+032D),但 Chrome(其中一个)决定只显示零宽度 space,并且无法显示下面的重音。如果我使用不带零宽度 space 的重音符号,我会遇到两个问题:

  1. 重音出现在前一个字母下方,而不是space
  2. 重音采用前一个字母的颜色(因为它们是组合的)

我目前的解决方法是在宽度为零的范围内使用普通竖线 | 字符,但这需要根据用于显示字符的字体进行位置调整:

<span
  style="
    position: relative;
    left: -0.1em;
    display: inline-block;
    width: 0px;
    color: red;
  "
>|</span>

这里有一个 jsfiddle 说明了我的解决方法的缺点。 是否有一个简单的解决方案,或者我是否需要做一些复杂的计算来确定要应用的位置调整,具体取决于用户的字体偏好?

div {
  position: relative;  
}
}div.serif {
  font-family: serif;
}
div.monospace {
  font-family: monospace;
}

p {
  top: 0;
  left: 0;
  margin: 0;
  font-size: 33vh;
  color: gray;
}
p.with-mark {
  position: absolute;
  top: 0.07em;
  color: blue;
}
span {
  position: relative;
  left: -0.1em;
  display: inline-block;
  width: 0px;
  color: red;
}
<div class="serif">
  <p class="without">missng</p>
  <p class="with-mark">miss<span>|</span>ng</p>
</div>
<div class="monospace">
  <p class="without">missng</p>
  <p class="with-mark">miss<span>|</span>ng</p>
</div>

我会保持跨度为空并添加一个框阴影来创建行:

div {
  position: relative;  
}
}div.serif {
  font-family: serif;
}
div.monospace {
  font-family: monospace;
}

p {
  top: 0;
  left: 0;
  margin: 0;
  font-size: 33vh;
  color: gray;
}
p.with-mark {
  position: absolute;
  top: 0.03em;
  color: blue;
}
span {
  display:inline-block;
  height:0.7em;
  box-shadow:0px 0 0 2px red;
  position:relative;
}
span::after {
  content:"^";
  position:absolute;
  top:100%;
  left:50%;
  transform:translate(-50%);
  color:red;
  font-size:0.3em;
}
<div class="serif">
  <p class="without">missng</p>
  <p class="with-mark">miss<span></span>ng</p>
</div>
<div class="monospace">
  <p class="without">missng</p>
  <p class="with-mark">miss<span></span>ng</p>
</div>