2

I need to get the height of a textarea. Seemingly so simple but it's driving me mad.

I have been researching for ages on stackoverflow with no luck: textarea-value-height and jquery-js-get-the-scrollbar-height-of-an-textarea and javascript-how-to-get-the-height-of-text-inside-of-a-textarea, among many others.

This is how it looks currently:

picture of a dialog window with a textarea

This is how I want it to look, open a full height:

picture of a dialog window with a textarea open at full height.

Here is my html:

 <textarea id="history" class="input-xxlarge" placeholder="Enter the content ..." rows="13"></textarea>

CSS:

 .input-xxlarge {
    display: inline-block;
    height: auto;     
    font-size: 12px;
    width: 530px;
    resize: none;
    overflow: auto;
 }

jQuery:

 var textarea = $('#history');

I've tried (inter alia):

1. textarea.height() --> always returns 0
2. textarea.ready(function() { // wait for DOM to load
      textarea.height();
   }
3. getting scrollheight from textarea as an HTMLTextareaElement (i.e. DOM Element) --> returns 0
4. var contentSpan = textarea.wrapInner('<span>');
   var height = contentSpan.height(); --> always returns 0

Please help, I'm at my wit's end!

Community
  • 1
  • 1
Tone
  • 990
  • 4
  • 14
  • 31
  • 2
    I'm assuming the missing `.` before `input-xxlarge` is an error in your post. – Mooseman Oct 30 '13 at 13:49
  • You can check out [this answer](http://stackoverflow.com/questions/3341496/javascript-how-to-get-the-height-of-text-inside-of-a-textarea). – John Oct 30 '13 at 13:49
  • 1
    I'm getting a number [here](http://jsfiddle.net/mblase75/dDVqE/) (latest Chrome) -- perhaps you're running the code before the DOM has loaded? – Blazemonger Oct 30 '13 at 13:50
  • hi Mooseman, yes, the CSS is being correctly applied live. I will correct the pseudo-code. – Tone Oct 30 '13 at 13:55
  • hi Blazemonger, thanks for the comment. Number 2 in my 'I tried' section looked at that solution by using jQuery.ready() function on the element before checking the height. No luck – Tone Oct 30 '13 at 13:57
  • What about remove the overflow of the container ? – DaniP Oct 30 '13 at 14:00
  • Hi Blazemonger, thanks very much for your fiddle. Just tried it, works perfectly, as do many of the other stackoverflow fiddles that are in the posts I mention above. Frustratingly, mine doesn't on my application. – Tone Oct 30 '13 at 14:03
  • Hi Sandeep, thanks for the reply. I did try a jquery version of your suggested solution in number 4 of my 'I tried' section but it didn't work. – Tone Oct 30 '13 at 14:07
  • what says console when you run it strait from it? console.log($('#history').height()); – Dmitry Dvornikov Oct 30 '13 at 14:11
  • Thanks Danko. Tried textarea.css('overflow','visible') but no luck – Tone Oct 30 '13 at 14:13
  • Hi Dmitry, it says 0. That would suggest the DOM has not loaded yet, so I tried a $.ready() to make sure it does and still it returns a big fat 0 – Tone Oct 30 '13 at 14:15
  • Please try min-height:200px – Asif Oct 30 '13 at 14:16
  • or share you project if it not on localhost – Dmitry Dvornikov Oct 30 '13 at 14:19
  • http://www.jacklmoore.com/autosize/ – Asif Oct 30 '13 at 14:25

7 Answers7

6

Ok, I've found a solution. Whether it's the best solution, I don't know, but it works and that, frankly, is all I care about, having spent almost a day on this issue.

Here it is for anyone who faces the same problem:

  1. Select the textarea:

    var textarea = $('#history');
    
  2. Get the textarea's text:

    var text = textarea.text();
    
  3. Create a temporary div:

    var div = $('<div id="temp"></div>');
    
  4. Set the temp div's width to be the same as the textarea. Very important else the text will be all on one line in the new temp div!:

    div.css({
       "width":"530px"
    });
    
  5. Insert the text into the new temp div:

    div.text(text);
    
  6. Append it to the DOM:

    $('body').append(div);
    
  7. Get the height of the div:

    var divHeight = $('#temp').height();
    
  8. Remove the temp div from the DOM:

    div.remove();
    
isuruAb
  • 2,202
  • 5
  • 26
  • 39
Tone
  • 990
  • 4
  • 14
  • 31
  • 1
    I find the use of jQuery to be abhorrent in this day and age of beautiful ES6. [My experiment on CodePen](https://codepen.io/amcgregor/project/live/DkyNVO/) demonstrates two approaches, the first, line-based (for text areas without soft wrapping), the second an animatable approach using `scrollHeight` calculations. Both are essentially two lines and involve no duplication of the content being sized, nor jQuery. – amcgregor Jan 26 '20 at 00:44
  • [My own answer given](https://stackoverflow.com/a/59914813/211827) with a solution involving the addition of no JavaScript and the removal of a small amount of CSS, as well as an efficient jQuery-free approach to calculation ([XY](http://xyproblem.info) to the actual problem), plus a minimal approach to making that dynamic. – amcgregor Jan 26 '20 at 04:06
3

Had a similar issue, in my case I wanted to have an expand button, that would toggle between two states (expanded/collapsed). After searching also for hours I finally came up with this solution:

Use the .prop to get the content height - works with dynamically filled textareas and then on a load command set it to your textarea.

Get the inner height:

var innerHeight = $('#MyTextarea').prop('scrollHeight');

Set it to your element

$('#MyTextarea').height(innerHeight);

Complete code with my expand button(I had min-height set on my textarea):

$(document).on("click", '.expand-textarea', function () {
    $(this).toggleClass('Expanded');

    if($(this).hasClass('Expanded'))
      $($(this).data('target')).height(1);
    else
      $($(this).data('target')).height($($(this).data('target')).prop('scrollHeight'));
  });
Renet
  • 339
  • 6
  • 13
2

Modern answer: textarea sizing is a few lines of ES6 implementable two primary ways. It does not require (or benefit from) jQuery, nor does it require duplication of the content being sized.

As this is most often required to implement the functionality of auto-sizing, the code given below implements this feature. If your modal dialog containing the text area is not artificially constrained, but can adapt to the inner content size, this can be a perfect solution. E.g. don't specify the modal body's height and remove overflow-y directives. (Then no JS will be required to adjust the modal height at all.)

See the final section for additional details if you really, truly only actually need to fetch the height, not adapt the height of the textarea itself.

Line–Based

Pro: almost trivial. Pro: exploits existing user-agent behavior which does the heavy lifting (font metric calculations) for you. Con: impossible to animate. Con: extended to support constraints as per my codepen used to explore this problem, constraints are encoded into the HTML, not part of the CSS, as data attributes.

/* Lines must not wrap using this technique. */
textarea { overflow-x: auto; white-space: nowrap; resize: none }
for ( let elem of document.getElementsByTagName('textarea') ) {
    // Prevent "jagged flashes" as lines are added.
    elem.addEventListener('keydown', e => if ( e.which === 13 ) e.target.rows = e.target.rows + 1)

    // React to the finalization of keyboard entry.
    elem.addEventListener('keyup', e => e.target.rows = (elem.value.match(/\n/g) || "").length + 1)
}

Scrollable Region–Based

Pro: still almost trivial. Pro: animatable in CSS (i.e. using transition), though with some mild difficulty relating to collapsing back down. Pro: constraints defined in CSS through min-height and max-height. Con: unless carefully calculated, constraints may crop lines.

for ( let elem of document.getElementsByTagName('textarea') )
    elem.addEventListener('keyup', e => {
        e.target.style.height = 0  // SEE NOTE
        e.target.style.height = e.target.scrollHeight + 'px'
    })

A shocking percentage of the search results utilizing scrollHeight never consider the case of reducing size; for details, see below. Or they utilize events "in the wrong order" resulting in an apparent delay between entry and update, e.g. pressing enter… then any other key in order to update. Example.

Solution to Initial Question

The initial question specifically related to fetching the height of a textarea. The second approach to auto-sizing, there, demonstrates the solution to that specific question in relation to the actual content. scrollHeight contains the height of the element regardless of constraint, e.g. its inner content size.

Note: scrollHeight is technically the Math.max() of the element's outer height or the inner height, whichever is larger. Thus the initial assignment of zero height. Without this, the textarea would expand, but never collapse. Initial assignment of zero ensures you retrieve the actual inner content height. For sampling without alteration, remove the height override (assign '') or preserve (prior to) then restore after retrieval of scrolllHeight.

To calculate just the height of the element as-is, utilize getComputedStyle and parse the result:

parseInt(getComputedStyle(elem).height, 10)

But really, please consider just adjusting the CSS to permit the modal to expand naturally rather than involving JavaScript at all.

amcgregor
  • 1,228
  • 12
  • 29
1

Place this BEFORE any HTML elements.

<script src="/path/to/jquery.js"></script>

<script>
$(document).ready(function(){
var textarea = $('#history');
alert(textarea.height()); //returns correct height 
});
</script>

You obviously do not have to alert it. I was just using an easily visible example.

Zach
  • 442
  • 1
  • 5
  • 12
  • Hi Zach, thanks for the post. I assume the $(document).ready(...) makes sure the DOM is loaded? If so, I've already tried this using ('#history').ready(...) and this didn't work. – Tone Oct 30 '13 at 13:59
  • You want to wait until the *document* is ready (ie: loaded), not just `#history`. – Jeromy French Oct 30 '13 at 14:21
  • @Tone did you make sure you put the script in the head? – Zach Oct 30 '13 at 16:27
  • Zach, no I didn't do that. I'm using angularjs so it already is in a javascript file – Tone Oct 31 '13 at 07:03
1

Given a textarea with an id of "history", this jQuery will return it's height:

$('#history').height()

Please see a working example at http://jsfiddle.net/jhfrench/JcGGR/

Jeromy French
  • 11,812
  • 19
  • 76
  • 129
  • Thanks for taking the time to reply and doing the fiddle Jeromy. I did try that solution and while it all works beautifully in your fiddle and the others I tried, it simply returns zero in my application. – Tone Oct 30 '13 at 14:28
  • What version of jQuery are you using? And are you simply trying to get the height of the textarea, or are you trying to get the visible height of the textarea within a modal? – Jeromy French Oct 30 '13 at 14:29
  • Jeromy, using jquery-1.9.1 and trying to get the visible height of the textarea within the modal (a kendo dialog). Actually, I'm trying to get the height of the contents of the textarea. – Tone Oct 31 '13 at 07:04
1

You can also retrieve the height in pixels by using $('#history').css('height'); if you're not planning on doing any calculations.

D4V1D
  • 5,805
  • 3
  • 30
  • 65
  • hi destroydaworld, thanks for the comment. Unfortunately I do have to do a caclulation, of the contents of the textarea. Using this I then know how high to set the dialog that contains the textarea. – Tone Oct 31 '13 at 07:06
0

for current height in px:


height = window.getComputedStyle(document.querySelector('textarea')).getPropertyValue('height')

for current width in px:


width = window.getComputedStyle(document.querySelector('textarea')).getPropertyValue('width')

change 'textarea' to '#history' or like a css selector. or textarea, since a variable is declared to select element.

ANDuser
  • 71
  • 8