Textarea Auto Resize [by ImpressiveWebs]
Tags: Jquery, Out Source, JavaScript, Css3, Tips And Tricks

On a current project, I was trying to find a way to auto-resize a textarea according to some content that would be loaded in dynamically via Ajax. I didn’t know the height of the content and the textarea element doesn’t resize naturally like other HTML elements, so I needed to update the height of the element with JavaScript each time the content changed.

It seemed like a simple task. After doing a search to see what types of plugins and scripts were floating around to do this, the examples I found seemed a little overly complex. While most solutions seemed to incorporate some complex math calculations, I thought of a better way.

Using a Hidden Clone Element

A

<div>

element will naturally stretch to fit the height of its content (assuming no floats or absolutely positioned elements are involved). So to get the height of the textarea, I just need to do the following:

Grab the content loaded into the textarea

Create an invisible clone div

Give the clone the same width and typographical properties as the textarea

Place the content into the clone

Get the height of the clone

Apply the height of the clone to the height of the textarea

The Code

One of the keys to this solution is the CSS. As mentioned, the invisible clone needs to have the same typographical properties as the textarea. Not only does this include stuff line

font-size

and

font-family

, but also the

white-space

and

word-wrap

properties of the clone need to be set to mimic what happens inside the textarea.

First here’s the CSS for the textarea:

textarea {

width: 500px;

min-height: 50px;

font-family: Arial, sans-serif;

font-size: 13px;

color: #444;

padding: 5px;

} .noscroll {

overflow: hidden;

}

Take note that I’ve added a separate class with

overflow: hidden

, to prevent scrollbars from appearing. Normally this would not be a good thing to add to a textarea element, but because I’ll be resizing it with JavaScript, it’s fine. This class will be added to the textarea with JavaScript, to ensure that if JavaScript is turned off, the textarea will scroll normally. Here is the CSS I’ll be applying to the hidden clone element: .hiddendiv {

display: none;

white-space: pre-wrap;

width: 500px;

min-height: 50px;

font-family: Arial, sans-serif;

font-size: 13px;

padding: 5px;

word-wrap: break-word;

} A quick break-down: First, I set it to

display: none

because I don’t want it visible to the user. I believe this should be fine for screen readers, because I don’t want it read out to them either. If anyone has a better solution for hiding it for assistive devices, let me know. I’ve also set the

white-space

property to a value of “pre-wrap”. This ensures that lines will wrap correctly, but everything else gets pre-formatted. I’ve also set the width to be equal to the textarea, and duplicated a few typographical properties. In both examples, I’m giving the clone and the textarea a

min-height

so it will always start out at a standard, usable height. Now for the JavaScript (which is using jQuery, sorry ): $(function() {

var txt = $('#comments'),

hiddenDiv = $(document.createElement('div')),

content = null; txt.addClass('noscroll');

hiddenDiv.addClass('hiddendiv'); $('body').append(hiddenDiv); txt.bind('keyup', function() { content = txt.val();

content = content.replace(/

/g, '<br>');

hiddenDiv.html(content); txt.css('height', hiddenDiv.height()); });

});

This code assumes we’re targeting a single textarea element on the page. If you need this to affect more than one element, then just change the first line inside the function that defines the element we’re working with. I’m dynamically changing the height based on jQuery’s

keyup

event. You could easily change this to respond to an Ajax request instead, if you happen to be loading the content that way. Using

keyup

, however, is a good solution because it’s the most likely reason that you’ll want to auto-resize a textarea — user-entered data. What About IE6-8? I almost didn’t write this article, because the code wasn’t working at all in IE6-8. The reason for this had to do with the poor way IE handles grabbing content using innerHTML . So after I had written this simple solution that seemed to work in all the newer browsers, I came across this jQuery plugin . That solution uses the exact same method that I’m using (the cloned element), and it worked (mostly) in IE. So the line that I borrowed from that example that (mostly) fixed mine in IE was: // fixes the IE innerHTML problem

content = content.replace(/

/g, '<br>'); But even after adding this line, there was still an issue: Long, unbroken strings of text wouldn’t affect the height of the textarea (which isn’t a big problem, really). A simple fix was adding

word-wrap: break-word

to the CSS for the clone element.

Bugs? Problems?