html - contenteditable 中的光标在 Chrome 中无法正常运行

标签 html css google-chrome contenteditable blink

我有一个问题,当用户在 contenteditable div 内部但在实际文本之外单击时,光标跳到错误的位置。这似乎只在较新版本的 Chrome(以及 Opera)中才是问题:巧合的是,我在较旧的浏览器(Chrome 版本 55)中测试了我的示例,但问题根本不存在。在 Edge/IE11/FireFox 中也没有问题。

仅当用户单击文本行后面或位于两个黄色 divpagebreak 之间的空行时,才会出现此问题。光标在第一个 pagebreak div 上方结束。我不知道它是否直接相关,但是当删除类 flowboxdiv 时,问题就消失了。不幸的是,我无法从应用程序中删除类为 flowboxdiv

我在这个 fiddle 中放了一个例子来说明我的问题:https://jsfiddle.net/dymcn1ao/

<div class="textframe a">
    <div class="flowbox"></div>
    <article contenteditable="true">
        <p>
            <span>
                <span>Foo bar baz</span>
                <br>
                <span class="pagebreak" contenteditable="false" style="min-height: 80px"></span>
                <span>Foo bar baz</span>
                <br>
                <span>Lorem ipsum dolor sit amet, consectetur adi piscing elit.</span>
                <br>
                <br>
                <span class="pagebreak" contenteditable="false" style="min-height: 80px"></span>
                <br>
                <span>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</span>
            </span>
        </p>
    </article>
</div>

左边的文本字段有问题,右边的文本字段按预期工作,因为 .flowbox div 已被删除。

编辑 1:

我创建了一个可能更容易理解的新示例。 .textframe 中的其他元素(如 pagebreak 和 flowbox 元素)实际上有特定用途,因此不能忽视它们。这是改进后的演示的链接:https://jsfiddle.net/q4pu37dn/15/

最佳答案

更新 3(演示 3)


enter image description here

变化

我注意到不再有任何 position: relative用于 most current OP code这很好,但我相信这被遗忘了:

<span class='pagebreak spacer'contenteditable="false"></span>

我相信您最初使用的是 contenteditable="false"为了给你.pagebreak的额外功能,也防止它们被删除,所以我把它们加回去了。


比较

Demo 3 将我的解决方案与 OP code 放在一起来比较行为。 Demo 3 还具有 2 个按钮(每个内容编辑器 1 个)突出显示每个 <span>文本。以下是来自 OP 代码(右侧的内容编辑器)的类列表和来 self 的代码(左侧的内容编辑器)的每个类的等效列表。

  1. div.textframe ............... section.editor
  2. p.textOutline ............... article.content
  3. span.flowbox.spacer ...... mark.vertRule
  4. span.pagebreak.spacer .. mark.breaker

OP 关注的有 2 个要求:

  1. <span>s 周围的空白区域点击后,光标会跳转到内容区域的一 Angular 。

  2. 每行字符数必须与OP码当前容量一致。

这个问题已经存在很多年了,但原因是星云,所以如果你将这种异常视为一种行为,你可以通过灌输不同的行为来解决它。

Demo2Demo3 只需应用以下样式规则集即可满足这些标准:

演示 2

article p {display: table;...

演示 3

.content {display:table-cell;...

表格-单元格的行为是严格且完善的,AFAIK 是唯一的非 replaced element默认情况下符合它的内容并符合周围的表格元素。作为奖励,元素带有 display: table-cell (不是 <td> )不需要嵌套在 <tr> 中那是在 <table> 内.


演示3

.content { display: table-cell;...

Fiddle

/* Begin Defaults */

* {
  margin: 0;
  padding: 0;
  border: 0;
  box-sizing: border-box;
}

html,
body {
  background: white;
  font: 400 16px/1.45 Arial;
  height: 100%;
  width: 100%;
}

/* End Defaults */

/* Begin Optional Layout */

#page01 {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-evenly;
  align-items: flex-start;
  background: rgba(45, 99, 198, 0.6);
  margin: 0 auto 20px;
  height: fit-content;
  min-width: 100%
}

/* End Optional Layout */

/* Begin Primary Styles */

.editor {
  width: 350px;
  height: 600px;
  border: 1px solid black;
  background: #fff;
}

.vertRule {
  float: right;
  clear: right;
  width: 30px;
  height: 600px;
}

.content {
  display: table-cell;
  word-break: break-word;
}

mark {
  display: block;
  pointer-events: none;
}

.break {
  min-height: 80px;
}

/* End Primary Styles */

/* Begin Control */

/* https://jsfiddle.net/q4pu37dn/15 */

.textframe {
  width: 350px;
  height: 600px;
  border: 1px solid black;
  background: #fff;
}

.flowbox {
  float: right;
  clear: right;
  width: 30px;
  height: 600px;
}

.spacer {
  background: yellow;
}

.pagebreak {
  display: block;
  min-height: 80px;
}

/* End Control */

/* Begin Demo Test */

.btn {
  display: inline-block;
  font: inherit;
  margin: 5px 10px;
  padding: 2px 5px;
  border: 5px outset grey;
  border-radius: 8px;
  color: #000;
  cursor: pointer;
}

[type='checkbox']:checked+label {
  background: rgba(255, 12, 34, 0.75);
  border: 5px inset grey;
  color: #fff;
}

#outline1:checked+label+#outline2+label+hr+#page01>.editor>.content *,
#outline2:checked+label+hr+#page01>.textframe>#textOutline *:not(.spacer) {
  color: #fff;
  background: tomato;
  outline: 2px solid red;
}

#outline1:checked+label+#outline2+label+hr+#page01>.editor>.content>.break,
#outline2:checked+label+hr+#page01>.textframe>#textOutline>.spacer {
  background: yellow;
  outline: none;
}

/* End Demo Test */
<!-- Begin Demo Test -->

<input id="outline1" type='checkbox' hidden>
<label for='outline1' class='btn'>Outline 1</label>

<input id="outline2" type='checkbox' hidden>
<label for='outline2' class='btn'>Outline 2</label>

<hr>

<!-- End Demo Test -->

<!-- Begin Optional Layout Part 1 -->

<main id='page01'>

  <!-- End Optional Layout Part 1 -->

  <!-- Begin Primary Markup -->

  <section class="editor" contenteditable='true'>
    <mark class="vertRule" contenteditable='false'></mark>
    <article class='content'>
      <span>
      Clicking here is not a problem
    </span>
      <br>
      <br>
      <span>
      Lorem ipsum
    </span>
      <mark class="break" contenteditable='false'></mark>
      <span>
      Clicking here (on empty space, not directly on text) will put the caret above the first .break element.
    </span>
      <br>
      <br>
      <span>
      Lorem ipsum
    </span>
      <mark class="break" contenteditable='false'></mark>
      <br>
      <span>
      Clicking here is not a problem
    </span>
      <br>
      <br>
    </article>
  </section>

  <!-- End Primary Markup -->

  <!-- Begin Control -->

  <div class="textframe" contenteditable>

    <p id='textOutline'>

      <span class="spacer flowbox"></span>
      <span>
      Clicking here is not a problem
    </span>
      <br>
      <br>
      <span>
      Lorem ipsum
    </span>
      <span class="spacer pagebreak"></span>
      <span>
      Clicking here (on empty space, not directly on text) will put the caret above the first .pagebreak element.
    </span>
      <br>
      <br>
      <span>
      Lorem ipsum
    </span>
      <span class="spacer pagebreak"></span>
      <br>
      <span>
      Clicking here is not a problem
    </span>
      <br>
      <br>
    </p>
  </div>

  <!-- End Control -->

  <!-- Begin Optional Layout Part 2 -->

</main>

<!-- End Optional Layout Part 2 -->


更新 2(演示 2)


关于演示 1 的 OP:

"you solved it for my contrived example, yes. Unfortunately it is not possible to set those values on the elements in the actual app, the flow gets totally out of wack there."

参见Demo 2,它比Demo 1效果更好。因为它只使用定位元素,所以在流程上没有冲突。为了使Demo 2适应您的应用,您需要做的就是添加position:relative。到父元素。相关样式如下:

article p {display: table;...

有必要分配 position:relative嵌套在 .textframe 中的所有内容, 否则 static元素不会与定位元素交互。表格和表格组件遵守的规则不仅适用于其内容,还适用于它们与相邻元素的交互方式。


演示2

article p {display: table...

.container {
  width: 400px;
  float: left
}

.textframe {
  width: 350px;
  height: 650px;
  outline: 2px dotted lightblue;
  overflow: hidden;
  margin: 0 15px 0 0;
  /* Needed for long words */
  word-break: break-word;
}

.textframe article {
  position: relative;
  height: 650px; 
}

article p {
  display: table;
  margin: 0;
  position:relative;
}

.flowbox {
  width: 2px;
  height: 650px;
  float: right;
  clear: right;
  outline: 1px solid red;
}

.pagebreak {
  display: block;
  pointer-events:none;
  position:relative;
}
<div class="container">
      <h4>
       article p {display: table; position: relative;}<br>
       all children of .textframe have: position: relative;  
      </h4>
      <div class="textframe a">
        <div class="flowbox"></div>
        <article contenteditable="true">
           <p>
            <span>
              <span>Foo bar baz</span>
            <br>
            <mark class="pagebreak" contenteditable="false" style="min-height: 80px"></mark>
            <span>Foo bar baz</span>
            <br>
            <span>Lorem ipsum dolor sit amet, consectetur adi piscing elit.</span>
            <br>
            <br>
            <mark class="pagebreak" contenteditable="false" style="min-height: 80px"></mark>
            <br>
            <span>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</span>
            </span>
          </p>
          <hr>
        </article>
      </div>
    </div>


引用文献

MDN - Float

MDN - Position

CSS Tricks - Absolute Positioning Inside Relative Positioning

CSS Tricks - All About Floats

display: table/table-cell

word-break:break-word


关于html - contenteditable 中的光标在 Chrome 中无法正常运行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52310991/

相关文章:

CSS 在 Chrome 中不工作,在 firefox 中不工作

javascript - Onsen UI : button, 底部对齐

google-chrome - 哪个浏览器使用哪个HSTS预加载列表?

html - 从 HTML 输入控件创建列表或数组的正确方法

html - 为什么 css 过渡不起作用?

javascript - 在不向每个元素添加 tabindex 的情况下编辑 div 中元素的 tab 顺序

javascript - Uncaught ReferenceError : importScripts is not defined

html - flex-flow 设置为 column wrap 时的 Flex 容器宽度

javascript - android webview本地html文件与javascript,脚本不起作用

javascript - 我想向一个元素添加一个事件监听器,当相应的元素滚动到 View 中时该元素会被触发