3

It works so far on using the contenteditable attribute on the <div> tag with the autogrow feature of a textbox. Also the height transition of it. It all works good, except for one thing, deleting characters, to be specific, a line, will not animate its height, unlike adding new lines. I have still a little knowledge on 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;
}
<div class="autogrow" contenteditable="true"></div>

When I press Shift + Enter, it doesn't animate either, it does well though while pressing Enter. Just the removing of lines and the Shift + Enter key combination while entering a new line is the problem.

How to make it work? Can it be done using pure CSS? Or adding a javascript function for it?

Community
  • 1
  • 1
Cookie Ninja
  • 1,156
  • 15
  • 29

2 Answers2

3

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

Bounce back effect

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>
HiDeoo
  • 10,353
  • 8
  • 47
  • 47
  • Works good. Well, I'm still an amateur, that I didn't think these kind of approach, but it works well. I will appreciate if you will up vote my question, these will help others who experienced the same situation that I encounter. :) – Cookie Ninja Jul 19 '16 at 13:12
1

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/

Roysh
  • 1,542
  • 3
  • 16
  • 26
  • I modify your code to test out the deleting function using line counters by counting `
    `s. I'm using shift+enter keys for entering a new line. Maybe you can do some alteration on the code to make it work. It does work, but needs some coding. https://jsfiddle.net/wx38rz5L/609/
    – Cookie Ninja Jul 18 '16 at 09:37
  • I was actually thinking about you've done. Give me a few hours and I'll try to fix that – Roysh Jul 18 '16 at 09:43