Contenteditable height transition: animate after adding (shift+enter) and removing a line of text

前端 未结 2 1253
轻奢々
轻奢々 2021-01-21 05:30

It works so far on using the contenteditable attribute on the

tag with the autogrow feature of a textbox. Also the height transition of it.
相关标签:
2条回答
  • 2021-01-21 05:33

    It's kinda hacky, but it works.

    First, modify your CSS

    .autogrow {
      border: 1px solid rgb( 0, 0, 0 );
      padding: 10px;
    }
    @keyframes line_insert {
      from {
        height: 0px;
      }
      to {
        height: 20px;
      }
    }
    .autogrow[contenteditable] > div {
      animation-duration: 250ms;
      animation-name: line_insert;
    }
    .autogrow[contenteditable] {
      overflow: hidden;
      line-height: 20px;
    }
    

    Then add this jQuery that detects Shift + Enter events and appends a div whenever they occur

    $(".autogrow").keydown(function(e){
    
        if (e.keyCode == 13 && e.shiftKey || e.keyCode == 13)
        {
           $(this).animate({height: $(this).height()+20},200);
                    $(this).append('<div><br></div>');
        }
    });
    

    And that should work.

    Check fiddle https://jsfiddle.net/wx38rz5L/582/

    0 讨论(0)
  • 2021-01-21 05:59

    To avoid these issues, I personally use a solution not based on pure CSS animations / transitions which I found always have problems. For example, in your CSS implementation, there is a bounce back effect if using the Enter too fast (you can slow the animation down to see it better).

    Moreover, new lines handling is different between browsers, some will add <div><br></div>, some versions of IE add only <br>, etc.

    I've never been able to fix all these problems or found an implementation fixing all of these so I decided to not modify at all the behavior of the contenteditable, let the browser do is magic which works and instead, react to what's happening.

    We don't even have to worry about keys events like Shift + Enter or events like deletion, etc., all of these are natively handled by the navigator.

    I choose instead to use 2 elements: one for the actual contenteditable and one for the styling of my contenteditable which will be the one having height animations / transitions based on the actual height of the contenteditable.

    To do that, I'm monitoring every events that can change the height of a contenteditable and if the height of my styling element is not the same, I'm animating the styling element.

    var kAnimationSpeed = 125;
    var kPadding = 10;
    
    $('div[contenteditable]').on('blur keyup paste input', function() {
      var styleElement = $(this).prev();
    
      var editorHeight = $(this).height();
      var styleElementHeight = styleElement.height();
    
      if (editorHeight !== styleElementHeight - kPadding * 2) {
        styleElement.stop().animate({ height: editorHeight + kPadding * 2 }, kAnimationSpeed);
      }
    });
    .autogrowWrapper {
      position: relative;
    }
    
    .autogrow {
      border: 1px solid rgb(0, 0, 0);
      height: 40px; /* line-height + 2 * padding */
    }
    
    div[contenteditable] {
      outline: none;
      line-height : 20px;
      position: absolute;
      top: 10px; /* padding */
      left: 10px; /* padding */
      right: 10px; /* padding */
    }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    
    <div class="autogrowWrapper">
      <div class="autogrow"></div>
      <div contenteditable="true"></div>
    </div>

    0 讨论(0)
提交回复
热议问题