出于某种原因,我需要使用contenteditable div而不是普通的文本输入来输入文本.(对于一些javascript库)它工作正常,直到我发现当我设置contenteditable div使用时display: inline-block
,即使我点击div之外,它也会给div提供焦点!
我需要它只有当用户点击div而不是它周围时才给焦点div.目前,我发现当用户点击其他地方然后单击与div相同的行的位置时,它会关注它.
一个显示问题的简单示例:
HTML:
Input 1Input 2This is some unrelated content
This is some more unrelated content This is just some space to shows that clicking here doesn't mess with the contenteditable div but clicking the side mess with it.
CSS:
div.outside { margin: 30px; } div.text-input { display:inline-block; background-color: black; color: white; width: 300px; }
用于显示问题的JSFiddle
是否有一种方法(CSS或javascript都可以接受)使浏览器只在点击它时给焦点而不是点击同一行?
PS我注意到有类似的问题(链接到其他相关的帖子),但情况有点不同,提供的解决方案对我不起作用.
解释(如果您不在乎,请跳至下面的解决方法)
当您单击可编辑元素时,浏览器会将光标(也称为插入点)放置在单击元素内最近的文本节点中,与您单击的行位于同一行.文本节点可以直接位于被点击的元素内,也可以位于其子元素之一中.您可以通过运行下面的代码段并在大蓝框中单击来验证这一点.
.container {width: auto; padding: 20px; background: cornflowerblue;}
.container * {margin: 4px; padding: 4px;}
div {width: 50%; background: gold;}
span {background: orange;}
span > span {background: gold;}
span > span > span {background: yellow;}
text in an editable element
text in a nested div
text in a deeply nested span
Notice that you can get an insertion point by clicking above the first line or below the last. This is because the "hitbox" of these lines extends to the top and bottom of the container, respectively. Some of the other answers don't account for this!
我只能在Chrome和Safari中重现此行为,这表明这可能是与Webkit相关的问题.
在没有检查代码的情况下很难分辨出发生了什么,但我们至少可以怀疑问题在于触发浏览器中文本选择的一些错误机制.类比地,如果div
s不是满足的,则在最后一个字符后单击同一行文本将触发从行尾开始的文本选择.
解决方法是将contenteditable div
s 包装到容器元素中,并使容器样式化-webkit-user-select: none
以使其无法选择.
正如Alex Char在评论中指出的那样,这不会阻止鼠标在容器外部点击以在其中的文本开头触发选择,因为第一个contenteditable div
和(可选)祖先容器之间没有静态文本它.可能有更优雅的解决方案,但克服此问题的一种方法是在第一个有意义div
的文本选择之前插入一个零宽度的不可见的非空文本范围.
为什么非空?:因为在选择文本时会忽略空元素.
零宽度为何?:因为我们不想看到它......
为什么看不见?:因为我们不想要的内容被复制到与,比如说剪贴板Ctrl+A,Ctrl+C.
div.outside {
margin: 30px;
}
div.text-input {
display:inline-block;
background-color: black;
color: white;
width: 300px;
}
div.text-input-container {
-webkit-user-select: none;
}
.invisible {
visibility: hidden;
}
Input 1
Input 2
This is some unrelated content
This is some more unrelated content
This is just some space to shows that clicking here doesn't mess with the contenteditable div
but clicking the side mess with it.