Why Is My Contenteditable caret Jumping to the End in Chrome?

后端 未结 6 1600
攒了一身酷
攒了一身酷 2020-12-10 01:59

Scenario

I have a contenteditable

area, and within this area I may have some
6条回答
  •  执念已碎
    2020-12-10 02:23

    The problem is evident in the below example and can be remedied by changing the contentetiable wrapper to display:block, but that causes a very annoying Chrome bug -


    will be added when ENTER key is pressed

    [contenteditable="true"]{
      border: 1px dotted red;
      box-sizing: border-box;
      width: 100%;
      padding: 5px;
      outline: none;
      display: inline-block; /* prevents Chrome from adding 

    when pressing ENTER key. highly undesirable. */ } [contenteditable="false"]{ background: lightgreen; padding: 3px; border-radius: 3px; }
    item item item

    Lets try to fix it:

    I can see the problem with the combination of width being wider than the content and also of display: inline-block.

    I also do not want to use javascript if there's any possibility for a CSS fix.

    I would very much like to keep display: inline-block to prevent the mentioned above Chrome bug from happening, so it would seem a thing can be done with the width issue, by setting it to auto when the contenteditable gets focused, and wrapping everything with an element that will allow to fake the same width as before using a pseudo-element inside the contenteditable (only when focused)

    .wrapper{
      width: 100%;
      position: relative;
    }
    
    [contenteditable="true"]{
      border: 1px solid red;
      box-sizing: border-box;
      width: 100%;
      padding: 5px;
      outline: none;
      display: inline-block;
    }
    
    [contenteditable="true"]:focus{
      border-color: transparent;
      width: auto;
    }
    
    [contenteditable="true"]:focus::before{
      content: '';
      border: 1px solid red; /* same as "real" border */
      position: absolute;
      top:0; right:0; bottom:0; left:0;
    }
    
    [contenteditable="false"]{
      background: lightgreen;
      padding: 3px;
      border-radius: 3px;
    }
    item item item

    The above solution is good for some situations, but not when the lines wrap and on the last like, the last element is a node:

    .wrapper{
      width: 100%;
      position: relative;
    }
    
    [contenteditable="true"]{
      border: 1px solid red;
      box-sizing: border-box;
      width: 100%;
      padding: 5px;
      outline: none;
      display: inline-block;
    }
    
    [contenteditable="true"]:focus{
      border-color: transparent;
      width: auto;
    }
    
    [contenteditable="true"]:focus::before{
      content: '';
      border: 1px solid red; /* same as "real" border */
      position: absolute;
      top:0; right:0; bottom:0; left:0;
    }
    
    [contenteditable="false"]{
      background: lightgreen;
      padding: 3px;
      border-radius: 3px;
    }
    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris item item item

    Lets just use javascript and place a br element at the end, if one is not there (it cannot be removed by selecting all and deleting the content):

    var elem = document.body.firstElementChild;
    
    if( !elem.lastChild || elem.lastChild.tagName != 'BR' )
        elem.insertAdjacentHTML('beforeend', '
    ')
    [contenteditable="true"]{
      border: 1px solid red;
      box-sizing: border-box;
      width: 100%;
      padding: 5px;
      outline: none;
      display: inline-block;
    }
    
    [contenteditable="false"]{
      background: lightgreen;
      padding: 3px;
      border-radius: 3px;
    }
    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris item item item

提交回复
热议问题