Issue with cursor behavior in contenteditable field on Chrome

Recently, I encountered an issue where the cursor would jump to the wrong place when a user clicked inside a contenteditable div, but not directly on the text. This problem seems to be isolated to newer versions of Chrome and Opera. Interestingly, when I tested the same example in an older version of Chrome (version 55), the issue did not occur at all. Furthermore, there were no problems in Edge, IE11, or Firefox.

The specific scenario causing this issue is when a user clicks behind a line of text or on an empty line located between two yellow divs with the class pagebreak. The result is that the cursor ends up above the first pagebreak div. Strangely enough, the problem disappears when the div with the class flowbox is removed. However, removing this particular div is not an option for me as it serves a necessary function within the app.

To provide a better understanding of the issue, I have created a demo showcasing the problem: 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>

In the provided demo, the textfield on the left exhibits the issue while the one on the right functions correctly due to the removal of the .flowbox div.

Edit 1:

To make the problem clearer, I have crafted a more simplified example. It's worth noting that elements like the pagebreak and flowbox within the .textframe have specific purposes and can't simply be omitted. For a better demonstration, refer to the updated demo here: https://jsfiddle.net/q4pu37dn/15/

Answer №1

Update 3 (Demo 3)


https://i.sstatic.net/V8YJ5.gif

Modifications

I have observed that in the most current OP code, there is no longer a use of position: relative, which is a positive change. However, I think one thing has been overlooked:

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

I believe you initially included contenteditable="false" to provide additional functionality to your .pagebreaks and prevent them from being deleted, so I have re-added them.


Comparative Analysis

Demo 3 displays my solution alongside the OP's code for comparison. In addition, Demo 3 showcases 2 buttons (one for each content editor) that highlight each <span> of text. Below is a list of classes from the OP's code (the content editor on the right) and their equivalent classes in my code (content editor on the left).

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

The OP has two specific requirements:

  1. Clicking the empty areas around the <span>s should move the cursor to the corner of the content area.

  2. Ensuring the number of characters per line remains consistent with the OP's current capacity.

This issue has persisted for years, but its root cause remains unclear. By treating this anomaly as a behavior pattern, we can potentially address it by introducing alternative behaviors.

Demo 2 and Demo 3 comply with these criteria by implementing the following style rulesets:

Demo 2

article p {display: table;...

Demo 3

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

The behavior of table-cells is rigid and well-established, and to my knowledge, they are the only non-replaced element that inherently conforms to its content and surrounding table elements. Additionally, an element with display: table-cell does not require nesting inside a <tr> within a <table>.


Demo 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 */

<!-- Details skipped for brevity -->

/* 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'>
      <!-- Content here -->
    </article>
  </section>

  <!-- More details omitted -->

</main>

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


Update 2 (Demo 2)


Regarding Demo 1:

"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."

Check out Demo 2; it performs better than Demo 1. By utilizing only positioned elements, conflicts in flow are avoided. To adapt Demo 2 to your application, simply add position:relative to the parent elements. The relevant style is specified below:

article p {display: table;...

It was crucial to assign position:relative to everything nested within .textframe to ensure proper interaction between static and positioned elements. Tables and their components adhere to certain rules that govern not only their content but also their relationships with neighboring elements.


Demo 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>
            <!-- Nested span elements -->
          </p>
          <hr>
        </article>
      </div>
    </div>


References

MDN - Float

MDN - Position

CSS Tricks - Absolute Positioning Inside Relative Positioning

CSS Tricks - All About Floats

display: table/table-cell

word-break:break-word


Answer №2

It seems like the issue lies within the display. My suggestion would be to change the span to a div element, as that seemed to resolve the problem. Please let me know if this solution works for you, or if I have misunderstood your question.

Unfortunately, I am unable to provide a detailed explanation as to why this issue occurred in the first place.

Note - Moving forward, it is recommended to use div elements instead of spans to avoid similar issues.

.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>

Answer №3

This issue arises when the CSS property float: right; is used unnecessarily.

Avoid using float: right; in cases where it is not needed, as it can lead to various complications. In this situation, switching to inline-block elements such as <div class="flowbox"> and

<article contenteditable="true">
will resolve the problem.

Example with float:right causing problems:

.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>

The solution

Example with display:inline-block (without issues)

Note: The

<div class="flowbox"></div>
has been moved after the <article> element in this updated version.

.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>

Answer №4

After upgrading to the latest version of Chrome on my Linux/Ubuntu system, it appears that the issue has been resolved. I made a simple adjustment by removing the contenteditable attribute from the article and placing it on the specific spans that needed editing.

<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>

Answer №5

It seems like the issue lies with the presence of an empty span within the content. I encountered this problem while working on a project that involved contenteditable, where the cursor appeared but was unable to move.

I recommend removing any empty spans from your p tags in order to address this issue – this can be done by simply deleting the span when using backspace or delete keys.

Alternatively, you may want to check out CKEDITOR, as it offers a solution to this problem.

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>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

"What is the purpose of using the `position: absolute` property for movement transitions while deleting an item from a list

Click here to see an example where items smoothly move in a list when one item is removed. To achieve this effect, the element needs to be styled with: .list-complete-leave-active { position: absolute; } I'm curious as to why it doesn't work w ...

What is the best way to enhance the appearance of a list item that includes a visited hyperlink?

Currently, I am utilizing Stylebot in Chrome to modify certain styles on a webpage that I frequently browse. My goal is to conceal elements in a list that have links I have already visited. For instance, there is a <tr> with the class table-row, and ...

Taking pictures with the camera in three.js on an iPhone

While working on a project that required capturing the camera video stream as a texture in three.js for mobile phones, I encountered an issue. The code I was using ran smoothly on Android devices but not on iPhones. Ideally, when the user grants permission ...

Issues with spacing in navigation bar

I've been searching and experimenting for hours, but I can't seem to make it work. In my "inline-form," I have a button on the left, an input field in the middle, and a button on the right within a navbar. Everything displays correctly when the ...

Can I create personalized animations using Compass?

I am curious about how to convert this code into Compass mixins @-webkit-keyframes shake { 0% { -webkit-transform: translate(2px, 0px) rotate(0deg); } 10% { -webkit-transform: translate(-1px, 0px) rotate(-1deg); } 20% { -webkit-transform: tran ...

Extracting and retrieving data using JavaScript from a URL

After reviewing some code, I am interested in implementing a similar structure. The original code snippet looks like this: htmlItems += '<li><a href="show-feed.html?url=' + items[i].url + '">' + items[i].name + '& ...

Why is the Google Map missing from the Bootstrap modal dialog?

I have multiple links on my website, each describing a different location with unique map data. I would like to display a modal bootstrap dialog with an embedded Google map when a user clicks on any of the links - ensuring that the location shown correspon ...

Grid items displaying incorrectly due to text alignment issues

I'm facing an issue where I need to separate text and the money part, and also align the text in a way that when viewed in smaller text sizes, the money part moves to the next line. .outdoor-card { display:flex; flex-wrap: wrap; width: 100%; ...

Displaying numerous Google charts within a Bootstrap carousel

A bootstrap carousel has been implemented to showcase our company's data. The carousel includes a bootstrap table, images, and two Google charts: a pie chart and a stacked bar chart. The issue arises when the active class is not maintained for the Go ...

A hover effect in CSS that utilizes a psuedo element to overlay the primary element

When hovering, I want to achieve an effect that looks similar to the display below: To view my website, click here The relevant code is shown below with the !important attributes removed: .cta-button-menu, .cta-button-menu::before { transitio ...

Add a border to the element if its height exceeds 300 pixels

My web page has a dynamic element with an unpredictable height. As more content is added, the element grows, but I have restricted it with a max-height: 300px;. However, I would like to add a hint to the user when the element reaches its maximum height by ...

Obtain the Chosen Item from a List Box Using JQuery and Separate by Commas

Seeking further assistance with the following issue. I have set up the code on jsfiddle at... http://jsfiddle.net/justinerswell/feDTU/ I am looking to extract the last item in the substr and then work backwards to fill in the necessary fields. Appreciat ...

Struggling to unlock the mystery of a jammed trigger box

I'm currently working on implementing a small 'trigger box' that will expand upon clicking. It was functional before, but it seems to be encountering an issue now and I'm unsure of the cause. While I have some understanding of HTML and ...

Feeling trapped during the process of setting up a intricate jQuery Image Slider

I've hit a roadblock while trying to make changes to the slider located at THIS URL. In the current setup, each thumbnail corresponds to one main display image. Clicking on a thumbnail displays a single image and then proceeds to slide to the next th ...

What is the best way to retrieve the content of HTML tags from a string using JavaScript or AngularJS?

I have a string with mixed content of HTML tags and text. Here is an example: var str = "<p></p><p><i>blabla</i></p><p><i><b>blaaaaaablaaaaa</b></i></p><iframe src="..." height=" ...

Load HTML 5 video on a webpage after all other elements have finished loading

Hello there! I'm trying to figure out a way to load an HTML 5 video after the page has already loaded. Currently, the video pauses all site interaction until it's fully loaded, but I'd prefer to have it display an image first and then autopl ...

Can you explain the significance of this?

Some may find this question silly, but I'm curious about the meaning behind certain elements in an ASPX page. For example, when there is code like this: <%@ Page Title="[$TITLES_listevents{uneditable}]" Language="C#" MasterPageFile="~/sitebase ...

Issues persist while attempting to save sass (.scss) files using Atom on a Mac

When attempting to work with sass files, I encountered an error message every time I tried to save the file: Command failed: sass "/Users/bechara/Desktop/<path of the file>/test.scss" "/Users/bechara/Desktop/<path of the file>/test.css" Errno: ...

Capture a section of the body background to incorporate into the canvas space

As a newcomer to the world of canvas, I have been learning from various sources about how it works. However, my goal is more dynamic and unique than what I've seen so far. I am looking to create a body background for my webpage that is responsive, cen ...

Load a page and sprinkle some contents with a slide effect

I am brand new to jQuery and just starting out, so please excuse me if this question seems basic or silly. I would like the header and footer of my page to stay in place while the center content slides in from the right side when the page loads. This websi ...