Nuevo tutorial en el que veremos paso a paso de cómo crear un textarea que crezca en altura de forma automática ajustándose a su contenido al más puro estilo Facebook. Para ello echaremos mano de la potentísima librería de javascript jQuery.

Autor:

Intentando mejorar cada día en este mundo tan cambiante de la programación. Sígueme en Twitter o en GitHub. Actualmente estoy disponible para contratar.
Descarga Demostración

Introducción

Si de algo no cabe duda es que en los últimos años las interfaces web han ido poco a poco enriqueciéndose, ajustándose a las necesidades del usuario y mejorando la experiencia de mismo a la hora de usar la aplicación.

Poco a poco, los grandes sitios como Facebook o Yahoo! han ido modificando los controles aburridos y sosos estándar de HTML para hacerlos más vistosos, y sobre todo, más usables.

Cada vez son más los sitios web que incorporan mejoras y nuevos controles alternativos a los básicos que HTML ofrece.

Así pues no es raro, sino bastante típico encontrarse controles como campos de texto con autocompletado de palabras, o textareas que se ajustan en altura, y nosotros, no deberíamos quedarnos atrás.

Al finalizar este tutorial, serás capaz de implementar controles del tipo textarea que crezcan automáticamente en altura dentro de tu sitio web gracias a jQuery.

¿Cómo funcionará nuestro textarea?

La verdad es que como siempre, buscando por internet he visto varios métodos para crear este tipo de controles. La primera solución con la que me encontré, y la primera que me vino a la cabeza, se basaba en la creación de un temporizador que revisaba cada X milisegundos el texto contenido en el textarea y ajustaba su altura.

No era mala idea, pero continué buscando, ya que nunca me acabaron de convencer los timers en Javascript.

La segunda solución que encontré se basaba en la escucha de los eventos keypress y la propiedad scrollHeight del textarea para así ajustar la altura.

Para que el textarea se ajuste al tamaño de texto, dos cosas son importantes: el evento keypress y la propiedad scrollHeight.

Me pareció una mejor solución, pero al implementarlo no me acaba de convencer, ya que su funcionamiento no era todo lo fino que esperaba.

Al final una idea surgió en mi cabeza para mejorar el script, por lo que dejé de googlear y me puse manos a la obra para probar si funcionaría.

Mi idea era básicamente hacer un clon del textarea, exactamente con las mismas propiedades pero oculto y un poco menos ancho que el original. Luego, en cada pulsación de tecla en el textarea original, copiamos el texto al clon; de forma que en el clon, al ser mas estrecho saltará antes la barra de scroll y por lo tanto sabemos que ya podemos incrementar la altura de nuestro textarea original.

No se si existen mejores soluciones, pero para mí, fue la que mejor resultado me dió a la hora de implementarlo en Erasmusu, proyecto propio en el que trabamos desde los inicios de Cokidoo.

Como siempre, veremos paso a paso cómo crear un textarea que crezca automáticamente en altura. ¡Vamos a ello!

Estructura pincipal

Como comentaba en la introducción, emplearemos jQuery para el desarrollo. La idea es que sea fácil de implementar en cualquier web, crearemos nuestro código como un plugin para jQuery. Si no sabes cómo se crean, puedes revisar el tutorial Cómo crear un Plugin para jQuery.

La estructura principal será pues la siguiente:

(function($){
    $.fn.extend({
        autoResize: function(options){
            this.each(function(){
            /*Código aquí*/
            });
        }
    })  
}(jQuery));

De esta forma podremos transformar nuestros controles del tipo textarea por defecto en textareas dinámicos:

$(SELECTOR).autoResize();

Echemos un vistazo a las opciones que tendrá nuestro plugin…

Opciones que se aceptarán

Para hacer un poco más dinámico el plugin y le pueda ser útil a más gente, se van a añadir unas cuantas opciones para poder personalizar un poco su funcionamiento y ajustarse a las necesidades de cada uno. Las opciones que aceptará son las siguientes:

  • (int) maxHeight – Maximo en altura que podrá alcanzar, luego se aplicará scrollbar.
  • (int) minHeight – Altura que tomará al coger el foco.
  • (string) textHold – Texto que se mostrará cuando esté vacío y sin foco.
  • (string) activeClass – Clase que se añadirá cuando recibe el foco.

Ninguna de las opciones anteriores es obligatoria, podemos optar por no configurarlas.

Paso 1: Recogiendo las opciones de forma adecuada

Lo primero que debe de hacer nuestro código es recoger y preparar de forma adecuada las opciones del plugin para que no salten errores en la siguiente ejecución del código.

Para ello creamos un nuevo objeto que recoge los valores que se pasan a la función o un valor predeterminado en su defecto.

//Si no se envía nada, se crea un objeto vacío para que no de error a continuación
if(!options){
    options = {};
}
//Almacena las opciones pasadas a la función o valores predeterminados en su defecto
var _options = {
    //Maximo en altura que podrá alcanzar, luego se aplicará scrollbar
    maxHeight: options.maxHeight || null,
    //Altura que tomará al coger el foco
    minHeight: options.minHeight || null,
    //Texto que se mostrará cuando esté vacío y sin foco
    textHold: options.textHold || null,
    //Clase que se añadirá cuando recibe el foco
    activeClass: options.activeClass || null
};

Paso 2: Crear el clon

Una vez tenemos la información preparada, llega el momento de crear el código que será ejecutado para cada textarea seleccionado con el selector de jQuery. Recordad, este código va dentro del this.each();.

Aquí se encuentra el código para crear el clon y las subscripciones a los eventos necesarias para el funcionamiento.

//Encapsulamos con jQuery
var $this = $(this);
//Establece el texto por defecto si ha sido establecido
if($this.val() == "" && _options.textHold){
    $this.val(_options.textHold);
}
//Guarda la altura inicial
$this.initHeight = $this.css("height");
//Establece el atributo CSS overflow según el caso
if(_options.maxHeight){
    $this.css("overflow", "auto");
}else{
    $this.css("overflow", "hidden");
}
//Para guardar el texto y comparar si hay cambios
var _value = null;
//Crea el clon del textarea
var $clon = $this.clone(true);
//Establece propiedades del clon y lo añade al DOM
$clon.css({
    visibility: "hidden",
    position: "absolute",
    top: 0,
    overflow: "hidden",
    width: parseInt($this.width())-10
});
$clon.attr("name","");
$clon.attr("id", "");
$this.parent().append($clon);
//Aux
var clon = $clon[0];
var me = $this;
//Eventos del textarea
$this.bind("keyup" , autoFit)
    .bind("focus", function(){})
    .bind("blur", function(){});
function autoFit(force){}

Como podéis ver, estamos dejando algunas partes del código simplemente con comentarios, no te preocupes, las iremos rellenando a continuación.

Paso 3: Rellenando los eventos

El evento focus

En este evento insertaremos el código que realice las siguientes tareas:

  • Comprobar si el texto que contiene el es mismo que el establecido mediante la opcion textHold, en dicho caso se borrará para comenzar a escribir.
  • Cambiar la altura a la establecida en la opcion minHeight
  • Añadir la clase establecida en la opcion activeClass

El código es el siguiente:

if(_options.textHold){
	if(this.value == _options.textHold){
		this.value = "";
	}
}
if(_options.minHeight){
	me.css("height", _options.minHeight+"px");
	$clon.css("height", _options.minHeight+"px");
	autoFit(true);
}
if(_options.activeClass){
	me.addClass(_options.activeClass);
}

Nada complicado, ¿no? Vamos a por el siguiente evento.

El evento blur

Cuando el textarea pierde el foco, tiene que deshacer algunas características establecidas en el evento focus:

  • Volver a poner el texto textHold en caso de que el valor esté vacío
  • Quitar la clase activeClass previamente añadida
if(_options.textHold){
	if(this.value == ""){
		this.value = _options.textHold;
		if(_options.minHeight && me.initHeight){
			$clon.css("height", me.initHeight);
			me.css("height", me.initHeight);
			autoFit();
		}
	}
}else{
	if(_options.minHeight && me.initHeight){
		$clon.css("height", me.initHeight);
		me.css("height", me.initHeight);
		autoFit();
	}
}
if(_options.activeClass){
	me.removeClass(_options.activeClass);
}

Una vez tenemos definido el comportamiento en ambos eventos, vamos a ver qué hará la función autoFit().

Paso 4: La función autoFit

Esta es la función que se encarga de ajustar el tamaño del textarea, comprobando siempre si el clon ha cambiado de tamaño o no. En realidad, lo que se comprueba del clon, es la propiedad scrollHeight, que nos devuelve el alto en pixels de la zona de scroll.

Es decir, el textarea puede tener por ejemplo 100px de scrollHeight y sólo 50px de height, lo que quiere decir que los otros 50px del textarea están ocultos.

La propiedad scrollHeight nos devuelve el alto total en pixels del contenido del elemento HTML.

Lo único que hace esta función es establecer el alto del textarea al scrollHeight sabiendo que el clon siempre va a ir un paso por delante al ser más estrecho que el original.

La función también tiene que encargarse de controlar el alto máximo y evitar que el textarea siga creciendo:

clon.value = me.val();
//Comprueba si ha cambiado el valor del textarea
if (_value != clon.value || force===true){
    _value = clon.value;
    var h = clon.scrollHeight;
    if(_options.maxHeight && h > _options.maxHeight){
    me.css("height", options.maxHeight + "px");
    }else{
        me.css("height", parseInt(h) + "px");
    }
}

Paso 5: Probando nuestro plugin con ejemplos…

Una vez hemos visto paso a paso cómo crear el plugin, os dejo con dos ejemplos de uso:

$("textarea").autoResize();

En este primer ejemplo, estamos activando el plugin para todos los textarea de nuestra página.

$("textarea").autoResize({textHold: "Escribe aquí tu texto", minHeight: 40, maxHeight: 400, activeClass: "active"});

En este segundo ejemplo estamos activando el plugin para todos los textarea y además estableciendo un texto por defecto, una altura mínima, una altura máxima y aplicando una clase de css “active” con la que podemos dar estilo a nuestro textarea.

Reflexión final

Bueno esto ha sido todo, espero que os resulte útil el tutorial y sobretodo os aporte a vuestra vida dura vida como programadores :) .

No dudéis en preguntar en los comentarios o incluso sugerir nuevas aportaciones o ideas para próximos tutoriales.

¡Nos vemos en la próxima publicación!

¿Necesitas desarrollar un proyecto web o para móviles? ¡Estamos disponibles!

Visitar Cokidoo

Cokidoo, los creadores de Ontuts, desarrollamos proyectos tecnológicos centrados en redes sociales y aplicaciones web, aplicaciones móviles y consultoría web y bases de datos.

Somos jóvenes, inquietos, versátiles, apasionados por la innovación y enfocados en las nuevas tecnologías. Con Ontuts tratamos de compartir nuestro conocimiento adquirido en los distintos proyectos, ayudando a la comunidad y mostrando nuestra capacidad tecnológica.

Si necesitas un presupuesto sin compromiso, estamos disponibles, no dudes en contactar con nosotros.

Comentarios en esta publicación (14 comentarios)

¿Te ha gustado esta publicación? ¡Puedes compartir tu opinión con todos nosotros! Simplemente pincha aquí mismo.

Puedo dar fe de que funciona de lujo en Erasmusu :)

buen plugin y buen post… me parece muy bueno que aparte de solo compartir el plugin para que hagan miles de copy/pates de tu codigo xP.. expliques como lo has creado

Ole tus webos! Estos post os harán grandes, gracias por compartirlo!

Ihan

no funciona en mozilla tal vez podrias decirme como podria hacer que funcione en ese navegador

eulerss

>>no funciona en mozilla tal vez podrias decirme como podria hacer que funcione en ese navegador

por acá en mozilla funciona perfecto, tengo versión 3.6.7

Saludos

Rhyudek1

en realidad creo que seria mas facil modificar los rows dependiendo de la cantidad de saltos de linea no crees ?

$(document).ready(function(){
$(“#insert_comment”).keyup(function(){
var content = $(this).val();
var saltos = content.substr_count(“\n”) + 1;
$(this).attr(“rows”, saltos);
});
});

te dejo tambien la funcion substr_count()
String.prototype.substr_count = function(){
var search = arguments[0];
var count = 0;
var pos = this.indexOf(search);
while ( pos != -1 ) {
count++;
pos = this.indexOf(search,pos+1);
}
return count;
}

saludos!

Rodrigo

@Rhyudek1 no creo, porque si se escribe un párrafo gigante no habrán saltos de línea.

Pregunta: E colocado el plugin y me a funcionado perfectamente pero al momento de ver mi diseño mas a fondo e notado que al momento de asignarle $(“textarea”).autoResize(); y una capa de estilo este mismo provoca que mi body de haga mas grande y descuadrando, aparece un scrolbar al pie, como puedo evitar esto?

Coloque la opción activeClass: “active” pero no cambio nada, sigue dando ese problema

buena aplicacion, me sirvio, he visto un pequeño detalle que ni importa pero si es posible encontrar la solucion mejor:

tengo el textarea con un height de 14px pero cuando pongo esta aplicacion en funcion al imprimirse en pantalla este tamaño cambia despues de medio segundo mas o menos a un tamaño igual al doble.

No se si sera solamente el mio pero sea cual sea si se puede resolver esto espero la respuesta.
gracias de nuevo!

Julian Ruiz

yo eh hecho algo parecido con un javasrcipt mi función es la siguiente lo unico que me falta es tomar el backspace del teclado

function onkeypressComentario(obj) {
if (obj.scrollHeight > parseInt(obj.style.height.replace(“px”, “”))) {
obj.style.height = obj.scrollHeight + “px”;
obj.id = “”
}
else if (obj.scrollHeight < parseInt(obj.style.height.replace("px", ""))) {
obj.style.height = obj.scrollHeight + "px";
obj.id = ""
}

if (parseInt(obj.style.height.replace("px", "")) < 80) {
obj.style.height = "80px"
}
}

Me gustaria que el javascript cuando le den la tecla backspace o corten el texto apequeñe le texto

Nacho

El problema con este plugin(por lo menos en la demostracion) es que si presionas una tecla y la dejas presionada hasta completar mas de una fila, el textarea no se agranda hasta no soltar la tecla.

Saludos

RICARDO

hOLA MI NOMBRE ES RICARDO, TENGO UNA DUDA LO QUE PASA QUE TENGO UN BLOG, Y QUISIERA HACERLO MUCHO MÁS LLAMATIVO, BUENO MI BLOG HABLO SOBRE TEMAS DE ADMINISTRACIÓN DE EMPRESAS Y MI PROBLEMA ES QUE QUIERO PONER UN TEXTAREA PARA QUE MIS VIISTANTES PUEDAN ENVIARME LOS TEMAS QUE DESEE HABLAR, BUENO YA LE TENGO EN HTM Y LO INSERTE A MI BLOG, PERO EL MENSAJE NO SE ENVIA A MI CORREO :

Propon tu tema:

BUENO ESO ES :
SALE BIEN PERO LO QUE SE ESCRIBE EN EL ESPACIO, NO LLEGA AL CORREO…
QUIZAS PUEDAS AYUDARME…..

RECUERDA QUE NO SÉ NADA DE ESTO … SOLO ES AFICIÓN Y BUENO ENCONTRÉ UNA BUENA PAGINA DE COMO HACERLA .. PERO NO DECIA NADA DE COMO SUBIRLA….