I use the following (with jQuery of course):
$(function () {
'use strict';
$("textarea").on('change keyup paste input', function () {
$(this).attr("rows", Math.max($(this).val().split("\n").length || 1, $(this).attr("rows") || 1));
$(this).css("width", $(this).css("width"));
}).trigger('change');
});
Note that it responds to various events, only increases the number of lines (i.e. doesn't decrease), triggers an initial change (e.g. to resize when browsing back to a form with lots of lines)