Friday, January 9, 2015

text area trick

http://www.impressivewebs.com/textarea-auto-resize/

Textarea Auto Resize

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 like 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('txtstuff');
    hiddenDiv.addClass('hiddendiv common');

    $('body').append(hiddenDiv);

    txt.on('keyup', function () {

        content = $(this).val();

        content = content.replace(/\n/g, '<br>');
        hiddenDiv.html(content + '<br class="lbr">');

        $(this).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(/\n/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?

Like the other solutions floating around, this could easily be turned into a plugin. In that case, I’d have to add a little more jQuery so that the characteristics of the clone element aren’t dependent on the CSS. Also, if the width of the textarea is fluid, then you’d have to use jQuery to grab that, and then apply it to the clone.
The solution I linked to in the previous section is just about perfect — you just need to add the word-wrap fix that I mentioned.
For a demo, you can view my JSFiddle using the link below. Just be sure to hit the “run” button before you test it. Let me know if you find any problems with it.
Update (Aug. 14/2012) The demo link above now points to an updated version with some of the fixes suggested in the comments along with some CSS improvements.

2 comments:

  1. MedsIT Nexus offers over 5 years of Medical Billing, Coding,
    Credentialing, Audit and Practice Management experience.
    We are transparent, customer oriented and dedicated because we believe “Together We Thrive.”
    premier medical billing services

    ReplyDelete
  2. Umm al-Quwain, also known as UAQ,
    is an emirate in the UAE and is located in the northern
    part of the country. The capital of the emirate also has the same name,
    just like all the other emirates. UAQ is a bright location for the setting up of a new company.

    business setup in umm al quwain

    ReplyDelete