135

How can I make a textarea automatically expand using jQuery?

I have a textbox for explaining the agenda of the meeting, so I want to expand that textbox when my agenda's text keep growing that textbox area.

brasofilo
  • 25,496
  • 15
  • 91
  • 179
Piyush
  • 5,145
  • 16
  • 49
  • 71

32 Answers32

171

If you dont want a plugin there is a very simple solution

$("textarea").keyup(function(e) {
    while($(this).outerHeight() < this.scrollHeight + parseFloat($(this).css("borderTopWidth")) + parseFloat($(this).css("borderBottomWidth"))) {
        $(this).height($(this).height()+1);
    };
});

See it working in a jsFiddle I used to answer another textarea question here.

To answer the question of doing it in reverse or making it smaller as text is removed: jsFiddle

And if you do want a plugin

@Jason has designed one here

Community
  • 1
  • 1
SpYk3HH
  • 22,272
  • 11
  • 70
  • 81
  • 1
    I had to remove + parseFloat($(this).css("borderTopWidth"))+ parseFloat($(this).css("borderBottomWidth")), else it infinitely loops with a textarea styled with bootstrap – blacelle Jan 29 '14 at 17:07
  • 3
    jQuery-less version: `if (this.clientHeight < this.scrollHeight) { this.style.height = this.scrollHeight + 'px'; }` – Georgii Ivankin Jul 27 '15 at 13:10
  • 3
    @metakungfu Well instead of just downvoting, maybe you can help improve the answer. I don't have any way of testing apple crap atm and safari for windows was discontinued a long time ago. So I can't really do anything to determine why it wouldn't work. Code-wise, there's nothing wrong with this solution. Are you sure it's the code that's breaking and not safari breaking in jsfiddle? safari is pretty picky and fiddle did just go through a major update. Mayeb you can open dev con and provide some more detail? – SpYk3HH Jul 21 '16 at 19:02
  • @SpYk3HH how can I get this to work for a textarea which is appended to the DOM please? – Tyler Oct 09 '16 at 00:25
  • @TimMarshall Read up on event delegation for dynamic events [**here**](http://learn.jquery.com/events/event-delegation/). jQuery recently, or sometime in last couple years, i only noticed recently, made a pretty nice tut site for better understanding jQuery. What you're asking about is simple event delegation on dynamic elements. That is to say, you use a static selector, such as `$(document)`, and then delegate the event to a dynamic selector (one that will select whatever is later loaded), such as `.on('click', 'textarea', func`. – SpYk3HH Oct 10 '16 at 16:03
  • 1
    also needs textarea overflow-y set to hidden to prevent flashing scroll – iulial Feb 09 '17 at 13:46
  • 2
    If I want to remove the added rows, the enlarged size of the textbox remains the same, is it possible that it can also automatically resize back? – Steven Apr 04 '18 at 09:59
117

I have tried lots and this one is great. Link is dead. Newer version is available here. See below for old version.
You can try by pressing and hold enter key in textarea. Compare the effect with the other auto expanding textarea plugin....

edit based on comment

$(function() {
   $('#txtMeetingAgenda').autogrow();
});

note: you should include the needed js files...

To prevent the scrollbar in the textarea from flashing on & off during expansion/contraction, you can set the overflow to hidden as well:

$('#textMeetingAgenda').css('overflow', 'hidden').autogrow()




Update:

The link above is broken. But you can still get the javascript files here.

Roman Pushkin
  • 5,639
  • 3
  • 40
  • 58
Reigel Gallarde
  • 64,198
  • 21
  • 121
  • 139
33

Grows / Shrinks textarea. This demo utilizes jQuery for event binding, but it's not a must in any way.
(no IE support - IE doesn't respond to rows attribute change)

DEMO PAGE


HTML

<textarea class='autoExpand' rows='3' data-min-rows='3' placeholder='Auto-Expanding Textarea'></textarea>

CSS

textarea{  
  display:block;
  box-sizing: padding-box;
  overflow:hidden;

  padding:10px;
  width:250px;
  font-size:14px;
  margin:50px auto;
  border-radius:8px;
  border:6px solid #556677;
}

javascript (updated)

$(document)
    .one('focus.textarea', '.autoExpand', function(){
        var savedValue = this.value;
        this.value = '';
        this.baseScrollHeight = this.scrollHeight;
        this.value = savedValue;
    })
    .on('input.textarea', '.autoExpand', function(){
        var minRows = this.getAttribute('data-min-rows')|0,
            rows;
        this.rows = minRows;
        rows = Math.ceil((this.scrollHeight - this.baseScrollHeight) / 16);
        this.rows = minRows + rows;
    });
vsync
  • 118,978
  • 58
  • 307
  • 400
  • This is a great solution. Very smooth, and can autoshrink as added benefit. But pardon my curiosity: could you share a little on why you make use of setTimeout rather than directly call autosize() ? – Bertie Apr 07 '14 at 05:37
  • 2
    because the code must wait a little for the letter you typed to be printed inside the textarea and therefor change the textarea's dimensions – vsync Apr 07 '14 at 09:17
  • Thanks a lot for your pointers. I will add http://stackoverflow.com/questions/779379/why-is-settimeoutfn-0-sometimes-useful as a good resource on how setTimeout helps even with the 0 millisecond value. – Bertie Apr 07 '14 at 10:06
  • 1
    I see, the solution is broken when the text is copied (CTRL+V) from any source. While, if the text is manually typed - this is awesome and very smooth. – Satya Kalluri Aug 27 '14 at 11:48
  • @Jason - please elaborate in what way doesn't it work? 404 / you see nothing / codepen error / you see everything but the javascript does not work / have console errors / etc. – vsync Aug 31 '14 at 09:33
  • the textarea doesn't grow when i add too much text, so yea the JS doesn't work – Jason Sep 01 '14 at 18:27
  • @Jason - please write in what browser / OS. you cannot just say "it doesn't work", because for me it works on IE/Chrome/Firefox (WIN7) versions dated to the end of 2013. – vsync Sep 01 '14 at 18:49
  • latest chrome, windows 7. i can say "it doesn't work" because it doesn't. you can't say "it works on my machine" because that's meaningless. i'll even give you steps to help repro the problem: 1) click your demo link. 2) add a bunch of jibberish. 3) note how textarea does not grow to compensate for text extending beyond its scroll height. – Jason Sep 02 '14 at 16:26
  • I see what you mean. you don't press the ENTER key...I will fix this. thanks for letting me know! – vsync Sep 03 '14 at 08:38
  • @Jason - fixed it. works for modern browsers except IE. – vsync Sep 04 '14 at 15:08
  • Breaks/collapses on keydown on refocus after a blur event. If repeated additional white lines are added each time to the end of the textarea. – Sir.Nathan Stassen Sep 08 '14 at 18:09
  • @Sir.NathanStassen - should be better now, changed the `focus` from `on` to `one` so calculations will occur once. – vsync Sep 08 '14 at 19:45
  • 1
    @vsync: how would you modify for multiple text areas? I.e. you have textarea1 and textarea2 and you want to allow both to grow? – jmoreno Apr 15 '15 at 23:59
  • 1
    This should be the top answer! I posted a question based on that if anyone is interested: http://stackoverflow.com/questions/29930300/force-resizement-when-importing-text-from-file – gsamaras Apr 28 '15 at 21:36
  • Trying to learn from this answer.. What is the difference between rows and this.rows? How would you explain the line - var minRows = this.getAttribute('data-min-rows')|0, rows; – Vali D Sep 11 '16 at 14:22
  • Also, how would you write it in a directive so that can be used in several locations? – Vali D Sep 11 '16 at 14:28
  • @vsync in your pen you divide by 17, is that that the line height? – Ally Murray Nov 06 '17 at 14:34
  • 1
    @AllyMurray - I went now and updated it to 16 since it seem to give better result. and yes, that is the expected line height – vsync Nov 06 '17 at 17:14
  • This solution worked really well for me, but I found that dividing by 20 `rows = Math.ceil((this.scrollHeight - this.baseScrollHeight) / 20); ` prevented any extra rows from being added, which eliminated unusable whitespace. – Ginger and Lavender Aug 04 '18 at 22:07
27

You can try this one

$('#content').on('change keyup keydown paste cut', 'textarea', function () {
        $(this).height(0).height(this.scrollHeight);
    }).find('textarea').trigger("change");
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="content">
  <textarea>How about it</textarea><br />
  <textarea rows="5">111111
222222
333333
444444
555555
666666</textarea>
</div>
reza.cse08
  • 5,938
  • 48
  • 39
21
KyleMit
  • 30,350
  • 66
  • 462
  • 664
CD..
  • 72,281
  • 25
  • 154
  • 163
11

Thanks to SpYk3HH, I started with his solution and turned it into this solution, which adds the shrinking functionality and is even simpler and faster, I presume.

$("textarea").keyup(function(e) {
    $(this).height(30);
    $(this).height(this.scrollHeight + parseFloat($(this).css("borderTopWidth")) + parseFloat($(this).css("borderBottomWidth")));
});

Tested in current Chrome, Firefox and Android 2.3.3 browser.

You may see flashes of the scroll bars in some browsers. Add this CSS to solve that.

textarea{ overflow:hidden; }
drolex
  • 4,993
  • 1
  • 18
  • 14
  • it doesn't work good at all :/ every character i type, it adds height. – vsync Oct 16 '13 at 15:14
  • 1
    It works perfect for me! There's definitely nothing in the simple code to do what you say it does. – drolex Oct 26 '13 at 00:54
  • 1
    yeah I see it now, your code must have the line which sets the height to 30 initially. this is probably an un-needed ilne because it forces the developer to tweak the code, instead of the code understand and adapt to the textarea, – vsync Oct 26 '13 at 11:41
  • 1
    That's incorrect. The developer does not need to tweak the code. Setting the height to 30 is required and it works for everything. The user never sees that happen. That is how it's able to shrink the textarea. The code does understand and adapt to the textarea. That is the whole point. – drolex Nov 07 '13 at 19:40
  • You are correct. demo page: http://jsbin.com/ObEcoza/2/edit (setting the height to `1px` seems to be better) – vsync Nov 07 '13 at 19:51
  • Nice one. I was also confused by the height setting to 30px and commented that out initially. But it works with the line just fine! – Petr Peller Feb 09 '14 at 13:27
  • However I just noticed the original solution works better. Your solution seems to have problems with textareas larger than windows size. Every keyup on such textareas seems to scroll whole window up and down. Also the initial (after the first keyup) textarea resize is noticeable. – Petr Peller Feb 09 '14 at 13:36
10

To define a auto expandable textarea, you have to do two things:

  1. Expand it once you click Enter key inside it, or type content more than one line.
  2. And shrink it at blur to get the actual size if user has entered white spaces.(bonus)

Here is a handmade function to accomplish the task.

Working fine with almost all browser ( < IE7 ). Here is the method:

    //Here is an event to get TextArea expand when you press Enter Key in it.
    // intiate a keypress event
    $('textarea').keypress(function (e) {  
       if(e.which == 13)   {   
       var control = e.target;                     
       var controlHeight = $(control).height();          
      //add some height to existing height of control, I chose 17 as my line-height was 17 for the control    
    $(control).height(controlHeight+17);  
    }
    }); 

$('textarea').blur(function (e) {         
    var textLines = $(this).val().trim().split(/\r*\n/).length;      
    $(this).val($(this).val().trim()).height(textLines*17);
    });

HERE is a post about this.

Laurel
  • 5,965
  • 14
  • 31
  • 57
Language Lassi
  • 2,520
  • 21
  • 24
6

I've used the Textarea Expander jQuery plugin before with good results.

richsage
  • 26,912
  • 8
  • 58
  • 65
  • 1
    A text box (input text element I presume) isn't multiline. Use a textarea but style it appropriately - rows, columns etc, and then use the auto-grow plugin as above. – richsage Jun 01 '10 at 13:43
4

Everyone should try this jQuery plugin: xautoresize-jquery. It's really good and should solve your problem.

danchoif2
  • 41
  • 2
4
function autosize(textarea) {
    $(textarea).height(1); // temporarily shrink textarea so that scrollHeight returns content height when content does not fill textarea
    $(textarea).height($(textarea).prop("scrollHeight"));
}

$(document).ready(function () {
    $(document).on("input", "textarea", function() {
        autosize(this);
    });
    $("textarea").each(function () {
        autosize(this);
    });
});

(This will not work in Internet Explorer 9 or older as it makes use of the input event)

benrwb
  • 853
  • 7
  • 15
  • in my project, as I am rendering whole things in the page by Jquery and typescript, your solution was the only way that I could solve my problem thanks – Harry Sarshogh Apr 15 '16 at 16:17
3

I just built this function to expand textareas on pageload. Just change each to keyup and it will occur when the textarea is typed in.

// On page-load, auto-expand textareas to be tall enough to contain initial content
$('textarea').each(function(){
    var pad = parseInt($(this).css('padding-top'));
    if ($.browser.mozilla) 
        $(this).height(1);
    var contentHeight = this.scrollHeight;
    if (!$.browser.mozilla) 
        contentHeight -= pad * 2;
    if (contentHeight > $(this).height()) 
        $(this).height(contentHeight);
});

Tested in Chrome, IE9 and Firefox. Unfortunately Firefox has this bug which returns the incorrect value for scrollHeight, so the above code contains a (hacky) workaround for it.

Simon East
  • 55,742
  • 17
  • 139
  • 133
3

I fixed a few bugs in the answer provided by Reigel (the accepted answer):

  1. The order in which html entities are replaced now don't cause unexpected code in the shadow element. (The original replaced ">" by "&ampgt;", causing wrong calculation of height in some rare cases).
  2. If the text ends with a newline, the shadow now gets an extra character "#", instead of having a fixed added height, as is the case in the original.
  3. Resizing the textarea after initialisation does update the width of the shadow.
  4. added word-wrap: break-word for shadow, so it breaks the same as a textarea (forcing breaks for very long words)

There are some remaining issues concerning spaces. I don't see a solution for double spaces, they are displayed as single spaces in the shadow (html rendering). This cannot be soved by using &nbsp;, because the spaces should break. Also, the textarea breaks a line after a space, if there is no room for that space it will break the line at an earlier point. Suggestions are welcome.

Corrected code:

(function ($) {
    $.fn.autogrow = function (options) {
        var $this, minHeight, lineHeight, shadow, update;
        this.filter('textarea').each(function () {
            $this = $(this);
            minHeight = $this.height();
            lineHeight = $this.css('lineHeight');
            $this.css('overflow','hidden');
            shadow = $('<div></div>').css({
                position: 'absolute',
                'word-wrap': 'break-word',
                top: -10000,
                left: -10000,
                width: $this.width(),
                fontSize: $this.css('fontSize'),
                fontFamily: $this.css('fontFamily'),
                lineHeight: $this.css('lineHeight'),
                resize: 'none'
            }).appendTo(document.body);
            update = function () {
                shadow.css('width', $(this).width());
                var val = this.value.replace(/&/g, '&amp;')
                                    .replace(/</g, '&lt;')
                                    .replace(/>/g, '&gt;')
                                    .replace(/\n/g, '<br/>')
                                    .replace(/\s/g,'&nbsp;');
                if (val.indexOf('<br/>', val.length - 5) !== -1) { val += '#'; }
                shadow.html(val);
                $(this).css('height', Math.max(shadow.height(), minHeight));
            };
            $this.change(update).keyup(update).keydown(update);
            update.apply(this);
        });
        return this;
    };
}(jQuery));
Community
  • 1
  • 1
Carlo Roosen
  • 1,025
  • 9
  • 15
3

Code of SpYk3HH with addition for shrinking size.

function get_height(elt) {
    return elt.scrollHeight + parseFloat($(elt).css("borderTopWidth")) + parseFloat($(elt).css("borderBottomWidth"));
}

$("textarea").keyup(function(e) {
    var found = 0;
    while (!found) {
        $(this).height($(this).height() - 10);
        while($(this).outerHeight() < get_height(this)) {
            $(this).height($(this).height() + 1);
            found = 1;
        };
    }
});
DSblizzard
  • 4,007
  • 7
  • 48
  • 76
3

This worked for me better:

$('.resiText').on('keyup input', function() { 
$(this).css('height', 'auto').css('height', this.scrollHeight + (this.offsetHeight - this.clientHeight));
});
.resiText {
    box-sizing: border-box;
    resize: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<textarea class="resiText"></textarea>
Nori
  • 121
  • 8
2

People seem to have very over worked solutions...

This is how I do it:

  $('textarea').keyup(function()
  {
    var 
    $this  = $(this),
    height = parseInt($this.css('line-height'),     10),
    padTop = parseInt($this.css('padding-top'),     10),
    padBot = parseInt($this.css('padding-bottom'),  10);

    $this.height(0);

    var 
    scroll = $this.prop('scrollHeight'),
    lines  = (scroll  - padTop - padBot) / height;

    $this.height(height * lines);
  });

This will work with long lines, as well as line breaks.. grows and shrinks..

superhero
  • 6,281
  • 11
  • 59
  • 91
2

Try this:

  $('textarea[name="mytextarea"]').on('input', function(){
    $(this).height('auto').height($(this).prop('scrollHeight') + 'px');
  });
tim
  • 2,530
  • 3
  • 26
  • 45
2

this worked for me perfectly well

 $(".textarea").on("keyup input", function(){
            $(this).css('height', 'auto').css('height', this.scrollHeight+ 
       (this.offsetHeight - this.clientHeight));
   });
1

For anyone using the plugin posted by Reigel please be aware that this will disable the undo functionality in Internet Explorer (go give the demo a go).

If this is a problem for you then I would suggest using the plugin posted by @richsage instead, as it does not suffer from this problem. See the second bullet point on Searching for the Ultimate Resizing Textarea for more information.

Community
  • 1
  • 1
1

I wrote this jquery function that seems to work.

You need to specify min-height in css though, and unless you want to do some coding, it needs to be two digits long. ie 12px;

$.fn.expand_ta = function() {

var val = $(this).val();
val = val.replace(/</g, "&lt;");
val = val.replace(/>/g, "&gt;");
val += "___";

var ta_class = $(this).attr("class");
var ta_width = $(this).width();

var min_height = $(this).css("min-height").substr(0, 2);
min_height = parseInt(min_height);

$("#pixel_height").remove();
$("body").append('<pre class="'+ta_class+'" id="pixel_height" style="position: absolute; white-space: pre-wrap; visibility: hidden; word-wrap: break-word; width: '+ta_width+'px; height: auto;"></pre>');
$("#pixel_height").html(val);

var height = $("#pixel_height").height();
if (val.substr(-6) == "<br />"){
    height = height + min_height;
};
if (height >= min_height) $(this).css("height", height+"px");
else $(this).css("height", min_height+"px");
}
Dave
  • 1,356
  • 10
  • 15
1

There is also the very cool bgrins/ExpandingTextareas (github) project, based on a publication by Neill Jenkins called Expanding Text Areas Made Elegant

Brian M. Hunt
  • 81,008
  • 74
  • 230
  • 343
1

I wanted animations and auto-shrink. The combination is apparently hard, because people came up with pretty intense solutions for it. I've made it multi-textarea-proof, too. And it isn't as ridiculously heavy as the jQuery plugin.

I've based myself on vsync's answer (and the improvement he made for it), http://codepen.io/anon/pen/vlIwj is the codepen for my improvement.

HTML

<textarea class='autoExpand' rows='3' data-min-rows='3' placeholder='Auto-Expanding Textarea'></textarea>

CSS

body{ background:#728EB2; }

textarea{  
  display:block;
  box-sizing: padding-box;
  overflow:hidden;

  padding:10px;
  width:250px;
  font-size:14px;
  margin:50px auto;
  border-radius:8px;
  border:6px solid #556677;
  transition:all 1s;
  -webkit-transition:all 1s;
}

JS

var rowheight = 0;

$(document).on('input.textarea', '.autoExpand', function(){
    var minRows = this.getAttribute('data-min-rows')|0,
        rows    = this.value.split("\n").length;
    $this = $(this);
    var rowz = rows < minRows ? minRows : rows;
    var rowheight = $this.attr('data-rowheight');
    if(!rowheight){
      this.rows = rowz;
      $this.attr('data-rowheight', (this.clientHeight  - parseInt($this.css('padding-top')) - parseInt($this.css('padding-bottom')))/ rowz);
    }else{
      rowz++;
      this.style.cssText = 'height:' + rowz * rowheight + 'px'; 
    }
});
Lodewijk
  • 3,741
  • 2
  • 18
  • 15
  • Note: i've noticed it sometimes works better with box-sizing: content-box. I'm not entirely sure why though, it should process padding correctly :( – Lodewijk Aug 03 '14 at 16:50
1

There are a lot of answers for this but I found something very simple, attach a keyup event to the textarea and check for enter key press the key code is 13

keyPressHandler(e){ if(e.keyCode == 13){ e.target.rows = e.target.rows + 1; } }

This will add another row to you textarea and you can style the width using CSS.

1

Let's say you're trying to accomplish this using Knockout... here's how:

In page:

<textarea data-bind="event: { keyup: $root.GrowTextArea }"></textarea>

In view model:

self.GrowTextArea = function (data, event) {
    $('#' + event.target.id).height(0).height(event.target.scrollHeight);
}

This should work even if you have multiple textareas created by a Knockout foreach like I do.

Barry Franklin
  • 1,781
  • 1
  • 27
  • 45
1

Simple Solution:

HTML:

<textarea class='expand'></textarea>

JS:

$('textarea.expand').on('input', function() {
  $(this).scrollTop($(this).height());
});
$('textarea.expand').scroll(function() {
  var h = $(this).scrollTop();
  if (h > 0)
    $(this).height($(this).height() + h);
});

https://fiddle.jshell.net/7wsnwbzg/

Pablo Werlang
  • 399
  • 3
  • 10
1

The simplest solution:

html:

<textarea class="auto-expand"></textarea>

css:

.auto-expand {
    overflow:hidden;
    min-height: 80px;
}

js (jquery):

$(document).ready(function () {
 $("textarea.auto-expand").focus(function () {
        var $minHeight = $(this).css('min-height');
        $(this).on('input', function (e) {
            $(this).css('height', $minHeight);
            var $newHeight = $(this)[0].scrollHeight;
            $(this).css('height', $newHeight);
        });
    });       
});
1

Solution with pure JS

function autoSize() {
  if (element) {
    element.setAttribute('rows', 2) // minimum rows
    const rowsRequired = parseInt(
      (element.scrollHeight - TEXTAREA_CONFIG.PADDING) / TEXTAREA_CONFIG.LINE_HEIGHT
    )
    if (rowsRequired !== parseInt(element.getAttribute('rows'))) {
      element.setAttribute('rows', rowsRequired)
    }
  }
}

https://jsfiddle.net/Samb102/cjqa2kf4/54/

samb102
  • 1,104
  • 5
  • 13
1

This is the solution I ended up using. I wanted an inline solution, and this so far seems to work great:

<textarea onkeyup="$(this).css('height', 'auto').css('height', this.scrollHeight + this.offsetHeight - this.clientHeight);"></textarea>
Trevor Meier
  • 81
  • 1
  • 3
1

function autoResizeTextarea() {
  for (let index = 0; index < $('textarea').length; index++) {
    let element = $('textarea')[index];
    let offset = element.offsetHeight - element.clientHeight;
    $(element).css('resize', 'none');
    $(element).on('input', function() {
      $(this).height(0).height(this.scrollHeight - offset - parseInt($(this).css('padding-top')));
    });
  }
}

https://codepen.io/nanachi1/pen/rNNKrzQ

this should work.

nanachi1
  • 11
  • 1
0

@Georgiy Ivankin made a suggestion in a comment, I used it successfully :) -- , but with slight changes:

$('#note').on('keyup',function(e){
    var maxHeight = 200; 
    var f = document.getElementById('note'); 
    if (f.clientHeight < f.scrollHeight && f.scrollHeight < maxHeight ) 
        { f.style.height = f.scrollHeight + 'px'; }
    });      

It stops expanding after it reaches max height of 200px

davidman77
  • 331
  • 3
  • 12
0

Old question but you could do something like this:

html:

<textarea class="text-area" rows="1"></textarea>

jquery:

var baseH; // base scroll height

$('body')
    .one('focus.textarea', '.text-area', function(e) {
        baseH = this.scrollHeight;
    })
    .on('input.textarea', '.text-area', function(e) {
        if(baseH < this.scrollHeight) {
            $(this).height(0).height(this.scrollHeight);
        }
        else {
            $(this).height(0).height(baseH);
        }
    });

This way the auto resize will apply to any textarea with the class "text-area". Also shrinks when text is removed.

jsfiddle:

https://jsfiddle.net/rotaercz/46rhcqyn/

Howard
  • 3,648
  • 13
  • 58
  • 86
0

Simple jQuery solution:

$("textarea").keyup(function() {
    var scrollHeight = $(this).prop('scrollHeight') - parseInt($(this).css("paddingTop")) - parseInt($(this).css("paddingBottom"));

    if (scrollHeight > $(this).height()) {
        $(this).height(scrollHeight + "px");
    }
});

HTML:

<textarea rows="2" style="padding: 20px; overflow: hidden; resize: none;"></textarea>

Overflow should be hidden. Resize is none if you do not want to make it resizable by mouse.

elano7
  • 1,584
  • 1
  • 18
  • 18
0

You can set the textarea's height to its scrollHeight on all events that change its potential size:

function setTextareaResponsive(id) {
   adjustTextareaHeight(id);

   $(window).on("resize", function() {
      adjustTextareaHeight(id);
   });

   $("#" + id).on("change input", function() {
      adjustTextareaHeight(id);
   });
}

function adjustTextareaHeight(id) {
   // set height to 1, so scrollHeight is related to linecount, not original textarea size
   $("#" + id).height(1);
   $("#" + id).height(document.getElementById(id).scrollHeight);
}

I personally like it better, when the height is not padded by the extra height (usually 12px) that scrollHeight provides. That's why I like to set the height to the number of lines multiplied by the lineHeight, in which case the function adjustTextareaHeight would look like this:

function adjustTextareaHeight(id) {
   var textarea = document.getElementById(id);

   // set height to 1, so scrollHeight is related to linecount, not original textarea size
   $("#" + id).height(1);
   var lineHeight = parseInt(getComputedStyle(textarea).lineHeight)
   var numberOfLines = Math.floor(textarea.scrollHeight / lineHeight)
   $("#" + id).height(lineHeight * numberOfLines);
}
Philipp Poropat
  • 131
  • 1
  • 6