内容可编辑的光标在Chrome中无法正常运行

时间:2018-09-13 09:44:10

标签: html css google-chrome contenteditable blink

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

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

在这个小提琴中,我整理了一个展示我的问题的示例:https://jsfiddle.net/dymcn1ao/

div

左侧的文本字段有问题,右侧的文本字段按预期工作,因为flowbox <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> 已被删除。

编辑1:

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

5 个答案:

答案 0 :(得分:1)

更新3(演示3)


  enter image description here

更改

我注意到most current OP code中不再使用任何position: relative都是好的,但我相信这已经被遗忘了:

  

<span class='pagebreak spacer' contenteditable =“ false” ></span>

我相信您最初使用contenteditable="false"是为了给您的.pagebreak提供额外的功能,并防止它们被删除,因此我将它们重新添加了。


比较

演示3 将我的解决方案与OP code并排进行比较。 演示3 还具有2个按钮(每个内容编辑器1个),突出显示每个<span>文本。以下是来自OP代码的类的列表(右侧的内容编辑器)以及与我的代码等效的每个类的列表(左侧的内容编辑器)。

  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周围的空白区域,光标将跳到内容区域的一角。

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

这个问题已经存在多年了,但是其原因是星云,因此,如果将这种畸变视为正常行为,则可以通过注入不同的行为来应对。

Demo2 Demo3 可以通过简单地应用以下样式规则集来满足这些条件:

演示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 Optionak 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

  

“您已经为我精心设计的示例解决了它,是的。不幸的是,无法在实际应用程序中的元素上设置这些值,流程在那里变得一团糟。”

请参见演示2 ,它的效果比演示1 更好。由于它仅使用定位的元素,因此在流程中没有冲突。为了使演示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


答案 1 :(得分:0)

问题出在显示器上,我对此还是陌生的,但是当我将跨度更改为div时,它可以正常工作,请让我知道它是否正确,或者我无法正确理解您的问题。

现在我不确定为什么会这样,因此无法为您提供深入的解释。

注意-在此之后,span和div的使用将不合适,因此也必须在其他位置将其更改为div。

.title {
  left: 20px;
}
.container {
  float: left;
  width: 400px;
}
.textframe {
  width: 311px;
  height: 650px;
  outline: 2px dotted lightblue;
  overflow: hidden;
  margin: 0 15px 0 0;
}
.textframe.b {
  left: 380px;
}
.textframe article {
  position: relative;
  height: 650px;
}
article p {
  margin: 0;
}
.pagebreak {
  display: block;
  position: relative;
  background: yellow;
}
.flowbox {
  width: 2px;
  height: 650px;
  float: right;
  clear: right;
  outline: 1px solid red;
}
<div class="container">
  <h4>
    With problem:
  </h4>
  <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>
          <div>Foo bar baz</div>
          <br>
          <div>Lorem ipsum dolor sit amet, consectetur adi piscing elit.</div>
          <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>
</div>
<div class="container">
  <h4>
    Without problem:
  </h4>
  <div class="textframe b">
    <article contenteditable="true">
      <p>
        <span>
          <span>Foo bar baz</span>
          <br>
          <span class="pagebreak" contenteditable="false" style="min-height: 80px"></span>
          <div>Foo bar baz</div>
          <br>
          <div>Lorem ipsum dolor sit amet, consectetur adi piscing elit.</div>
          <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>
</div>

答案 2 :(得分:0)

我正在Linux / Ubuntu上使用最新版本的Chrome,这似乎已经解决了问题。我刚刚从文章中删除了contenteditable,并将其放在您要编辑的范围内。

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

答案 3 :(得分:0)

发生此问题的原因是您使用float: right;

如果不需要CSS属性float: right;,请不要使用它。您可能会遇到很多问题。在您的情况下,您不需要它。取而代之的是,您将inline-block元素用作<div class="flowbox"><article contenteditable="true">

带有float:right的最小示例(有问题)

.textframe {
    width: 311px;
    height: 650px;
    outline: 2px dotted lightblue;
    overflow: hidden;
    margin: 0 15px 0 0;
}
.flowbox {
    width: 2px;
    height: 650px;
    float: right;
    clear: right;
    outline: 1px solid red;
}
.pagebreak {
    display: block;
    position: relative;
    background: yellow;
}
<div class="container">
  <h4>
    With problem:
  </h4>
  <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 CLICK ABOVE THIS WORDS 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>
</div>

解决方案

带有display:inline-block的最小示例(没有问题)

注意:现在,我将您的<div class="flowbox"></div>放在了<article>元素之后。

.textframe {
    width: 311px;
    height: 650px;
    outline: 2px dotted lightblue;
    overflow: hidden;
    margin: 0 15px 0 0;
}
.flowbox {
    width: 2px;
    height: 650px;
    outline: 1px solid red;
}
.pagebreak {
    display: block;
    position: relative;
    background: yellow;
}
.flowbox, article{display:inline-block;vertical-align:top;}
article{width: 305px;}
<div class="container">
  <h4>
    With problem:
  </h4>
  <div class="textframe a">
    <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 CLICK ABOVE THIS WORDS 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 class="flowbox"></div>
  </div>
</div>

答案 4 :(得分:0)

如果跨度为空,我认为跨度问题。我在使用contenteditable时遇到了这个问题,因此光标显示在此处,但是您无法使其移动。

我建议您从p到每个段落中删除跨度,以便如果跨度为空,请尝试在退格键/删除处将其删除。

或者参考CKEDITOR,因为它已经解决了该问题

article p, article div
{
    line-height: 1.25;
    margin-top: 12px;
    margin-bottom: 12px; /*  margin-bottom: 10px; removed for proper pagebreak 31-1-2017*/
    font-family: Helvetica;
}

.title {
  left: 20px;
}
.container {
  float: left;
  width: 400px;
}
.textframe {
  width: 311px;
  height: 650px;
  outline: 2px dotted lightblue;
  overflow: hidden;
  margin: 0 15px 0 0;
}
.textframe.b {
  left: 380px;
}
.textframe article {
  position: relative;
  height: 650px;
}
article p {
  margin: 0;
}
.pagebreak {
  display: block;
  position: relative;
  background: yellow;
}
.flowbox {
  width: 2px;
  height: 650px;
  float: right;
  clear: right;
  outline: 1px solid red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
  <h4>
    With problem:
  </h4>
  <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>
</div>
<div class="container">
  <h4>
    Without problem:
  </h4>
  <div class="textframe b">
    <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>
</div>