Chrome中的contenteditable中没有显示编辑光标

30

当您使用Chrome打开此页面(请参见Live demo)时:

<span id="myspan" contenteditable=true></span>

CSS:

#myspan { border: 0; outline: 0;}

JS :

JS:
$(myspan).focus();

这个可编辑的 span 获得了焦点(您可以开始输入内容,但是您可能没有看到光标),但我们没有看到“I”编辑光标。

如何让此光标显示?(注意:需要使用 outline:0,同时即使没有空格,该 span 也应为空白)。

注:在 Firefox 中,光标会显示。


尝试指定最小宽度和最小高度。空的 span 元素渲染后的宽度和高度为零,因此无法进行鼠标悬停操作。通过强制其具有几个像素的大小,就可以实现鼠标悬停操作。 - Woodrow Barlow
也许来自另一个问题的这个答案可以帮到你:https://dev59.com/Jm025IYBdhLWcg3wCxVN#6249440 - d.h.
@WoodrowBarlow 请看这里:http://jsfiddle.net/gs3p1a6r/4/ 或 http://jsfiddle.net/gs3p1a6r/4/embedded/result/,仍然存在错误。它已经聚焦了,但光标没有显示出来。 - Luke
我看到了,我以为你指的是鼠标光标,但你指的是闪烁的东西。看起来Doctus解决了它。 - Woodrow Barlow
9个回答

27
问题在于元素是内联元素。只需在CSS中添加display:block;即可解决问题。

$(myspan).focus();
#myspan {
    border: 0;
    outline: 0;
    display: block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<span id="myspan" contenteditable=true></span>


4
或者可能是 display:inline-block; - avee
1
@avee inline-block在谷歌浏览器中无法解决问题。 - imtheman
1
很奇怪,我在 Chrome 版本 51.0.2704.103 (64 位) 上测试没问题。也许是因为我用了 Bootstrap?使用 block 实际上使 span 表现得像一个 div - avee
3
稍微解释一下:内联元素如果没有内容会折叠为零宽度,而块级元素默认情况下为100%宽度。这就是为什么“inline-block”元素也受到相同问题影响的原因。 - Luke
问题不在于 spaninline,而是如果 inline 元素没有任何内容,则其宽度为 0。因此解决方案是确保元素具有一定的宽度,而 display: block; 正好可以实现这一点。 - Luke

18

我在左侧添加了填充,光标出现了。

#myspan
{
    border: 0; 
    outline: 0; 
    min-width: 100px; 
    height: 30px; 
    <b>padding-left: 1px;</b>
}

jsFiddle演示


1
可能是因为空的span宽度为0。如果光标需要出现在元素内部,那么除非你给它一些填充空间,否则它就没有空间可以出现在其中。这只是一个猜测。 - KyleMit
1
我又试了一下,添加 display: block 并删除其他的修改也可以生效:http://jsfiddle.net/gs3p1a6r/10/。看起来没有内容的内联元素不受 min-width 的影响? - Luke

8
.cont_edit {
  outline: 1px solid transparent;
}

能否提供一个 jsfiddle 或者将答案转化为代码片段?这对以后的参考很有帮助。顺便说一下,我不是那个给你点了踩的人! - Basj
由于页面上存在其他冲突的 CSS,我不得不使用这个 display: block 并使两个属性都变为 !important - turkinator

6
解决方案是将<span>更改为<div>(我看到其他问题中这解决了许多contenteditable问题),并添加min-width
确实,使用以下代码,<div>的大小将为0px x 18px!这就解释了为什么caret(编辑光标)会被隐藏!
HTML
<div id="blah" contenteditable=true></div>

CSS

#blah {
    outline: 0;
    position: absolute;
    top:10px;
    left:10px;
}

JS

$("#blah").focus();

然后,添加

min-width: 2px;

在CSS中,使用该代码可以使得插入符在Chrome浏览器中显示:http://jsfiddle.net/38e9mkf4/2/

谢谢。min-width对我来说很有效。在我的情况下,contenteditable元素的父元素是display: flex,所以空内容会使元素的宽度为零。 - undefined

6
这与空的ContentEditable区域呈现的方式有关。为了证明它不是焦点问题,向可编辑的div添加一些文本,然后将其删除。当最后一个字符消失时,光标将消失。
来自问题在contentEditable元素中将插入点位置设置为空节点 选择/范围模型基于对文本内容的索引,忽略元素边界。我相信不可能在没有文本的内联元素内设置输入焦点。当点击或使用箭头键时,无法将焦点设置到最后一个元素内。 如果将每个span设置为display:block,它几乎可以工作,尽管仍存在某些高度奇怪的行为,这取决于父容器中是否存在空格。通过float、inline-block和absolute position等技巧来欺骗显示为内联,使IE将每个元素视为单独的编辑框。相对定位的块元素彼此相邻可以工作,但这可能是不切实际的。

You could also try adding a zero-width character like &#8203;

document.getElementById('myspan').focus();
#myspan {
    border: 0;
    outline: 0;
}
<span id="myspan" contenteditable="true">&#8203;</span>


2
我在Chrome v89.0.4389.90上遇到的问题是,当使用contenteditable字段时,有时会在focusin时显示闪烁的光标,有时则不会。我发现当聚焦前该字段中已经有内容时,它总是会闪烁。而当没有内容时,就会出现这种有时会/有时不会的行为。

起初,我认为可能存在一些冲突的事件处理程序会不稳定地夺走焦点。我禁用了所有的事件绑定和计时器,但仍然出现同样的不稳定行为。然后我想可能是一些冲突的CSS,于是我禁用了所有样式表。至少现在行为是一致的:当该字段有内容时,光标始终闪烁;当该字段没有内容时,光标则不会始终闪烁。

我重新启用了绑定和样式表。我的div已经设置为display:block;,并且在最终计算的样式集中设置了min-widthmin-heightpadding。这里的其他答案都没有起作用。我确实在:empty:before上设置了一个placeholder,这可能是罪魁祸首。我将其注释掉后,行为再次变得一致,就像样式表被关闭时一样。奇怪的是,SO上的可运行片段使用了相同的计算CSS堆栈。我想保留placeholder,所以需要进一步研究我的实际代码库...

我能找到的唯一解决当前问题的方法是,通过创建一个空格并立即删除它,强制将光标放在空字段中。这是我在调试根本原因之前所能做的最好的解决方法。

//force caret to blink inside masks
let force_caret = function() {
  if (!this.textContent) {
    this.textContent = ' ';
    let r = document.createRange(),
      s = window.getSelection();
    r.setStart(this.childNodes[0], 0);
    r.collapse(true);
    s.removeAllRanges();
    s.addRange(r);
    this.textContent = '';
  }
}

//binds
let els = document.querySelectorAll("[contenteditable]");
for (let i = 0; i < els.length; i++) {
  els[i].addEventListener('focusin', force_caret, false);
}
/* styles irrelevant to the issue, added for visual assist */

:root {
  --b-soft: 1px solid silver;
  --bs-in: inset 0 1px 3px rgba(0, 0, 0, 0.3), 0 1px rgba(255, 255, 255, 0.1);
  --c-soft: gray;
  --lg-warm: linear-gradient(30deg, rgb(254, 250, 250), #eedddd);
}

body {
  font-family: system-ui, -apple-system, -apple-system-font, 'Segoe UI', 'Roboto', sans-serif;
}

[contenteditable] {
  outline: initial;
}

[contenteditable][placeholder]:empty:before {
  content: attr(placeholder);
  color: var(--c-soft);
  background-color: transparent;
  font-style: italic;
  opacity: .5;
  font-size: .9em;
}

.input {
  border-bottom: var(--b-soft);
  padding: .2em .5em;
}

.input_mask {
  display: flex;
  align-items: baseline;
  color: var(--c-soft);
}

.mask {
  box-shadow: var(--bs-in);
  border-radius: .2em;
  background: var(--lg-warm);
  font-weight: 500;
  border: 1px solid transparent;
  text-transform: uppercase;
  /* styles possibly relevant to the issue according to other proposed solutions */
  margin: 0 .4em .1em .4em;
  padding: .2em .4em;
  min-width: 3em;
  min-height: 1em;
  text-align: center;
}
<div data-type="tel" data-id="phone" class="input input_mask">
  <span>+1 (</span>
  <div maxlength="3" contenteditable="true" placeholder="111" class="mask"></div>
  <span>)</span>
  <div maxlength="3" contenteditable="true" placeholder="111" class="mask"></div>
  <span>-</span>
  <div maxlength="4" contenteditable="true" placeholder="1111" class="mask"></div>
  <span>x</span>
  <div maxlength="5" contenteditable="true" class="mask"></div>
</div>


1

对我而言,将可编辑div的内容设置为<br>有效。我尝试将其设置为nbsp;,但这会在我开始编辑之前在div中创建额外的字符空间。因此,我选择了这个:

<div id="blah" contenteditable=true><br></div>

结束:

<div id="blah" contenteditable=true>nbsp;</div>

希望这有所帮助。

1
添加一个CSS样式:

min-height: 15px;

你可能还需要
display: block;

contenteditable="true"标签添加到您的HTML内容中。

-3

我使用Chrome浏览器,你的代码运行良好。

尝试在你的CSS中使用cursor: text;。请参见这里


CSS中的光标指的是鼠标光标,它不一定在span占据的区域内。此外,我使用Chrome浏览器,演示无法正常工作。 - Luke
他只想看到光标出现。当他在输入时,他可以将其附加到页面上,并监听点击以检测是否单击了页面的其他部分,并再次从页面中删除它。 - PreFiXAUT

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接