Crear un área de texto con cambio de tamaño automático


366

Hubo otro hilo sobre esto , que he probado. Pero hay un problema: el textareano se reduce si elimina el contenido. No puedo encontrar ninguna forma de reducirlo al tamaño correcto: el clientHeightvalor regresa como el tamaño completo del textarea, no su contenido.

El código de esa página está abajo:

function FitToContent(id, maxHeight)
{
   var text = id && id.style ? id : document.getElementById(id);
   if ( !text )
      return;

   var adjustedHeight = text.clientHeight;
   if ( !maxHeight || maxHeight > adjustedHeight )
   {
      adjustedHeight = Math.max(text.scrollHeight, adjustedHeight);
      if ( maxHeight )
         adjustedHeight = Math.min(maxHeight, adjustedHeight);
      if ( adjustedHeight > text.clientHeight )
         text.style.height = adjustedHeight + "px";
   }
}

window.onload = function() {
    document.getElementById("ta").onkeyup = function() {
      FitToContent( this, 500 )
    };
}

La respuesta aceptada para el hilo que vinculaste funciona para mí. Agregar saltos de línea expande el área de texto y eliminarlos reduce el área de texto. ¿Qué navegador estás usando?
EndangeredMassa

3
Mi función hace error. Es necesariamente escribir una nueva línea al final de la línea. Esta es una mejor solución. james.padolsey.com/javascript/jquery-plugin-autoresize

Puede probar mi complemento para esto: github.com/AndrewDryga/jQuery.Textarea.Autoresize
Andrew Dryga


Respuestas:


230

Esto funciona para mí (Firefox 3.6 / 4.0 y Chrome 10/11):

var observe;
if (window.attachEvent) {
    observe = function (element, event, handler) {
        element.attachEvent('on'+event, handler);
    };
}
else {
    observe = function (element, event, handler) {
        element.addEventListener(event, handler, false);
    };
}
function init () {
    var text = document.getElementById('text');
    function resize () {
        text.style.height = 'auto';
        text.style.height = text.scrollHeight+'px';
    }
    /* 0-timeout to get the already changed text */
    function delayedResize () {
        window.setTimeout(resize, 0);
    }
    observe(text, 'change',  resize);
    observe(text, 'cut',     delayedResize);
    observe(text, 'paste',   delayedResize);
    observe(text, 'drop',    delayedResize);
    observe(text, 'keydown', delayedResize);

    text.focus();
    text.select();
    resize();
}
textarea {
    border: 0 none white;
    overflow: hidden;
    padding: 0;
    outline: none;
    background-color: #D0D0D0;
}
<body onload="init();">
<textarea rows="1" style="height:1em;" id="text"></textarea>
</body>

Si quieres probarlo en jsfiddle , comienza con una sola línea y crece solo la cantidad exacta necesaria. Está bien para un solo textarea, pero quería escribir algo en el que tendría muchos, muchos, muchos de esos textareacorreos electrónicos (casi tanto como uno normalmente tendría líneas en un documento de texto grande). En ese caso es realmente lento. (En Firefox es increíblemente lento). Así que realmente me gustaría un enfoque que use CSS puro. Esto sería posible con contenteditable, pero quiero que sea de texto sin formato.


13
¡Lo hace! Hecho un jsfiddle para ti: jsfiddle.net/CbqFv Ahora funciona en Chrome, Firefox e IE8, aunque es un poco irregular en IE8. A medida que aumenta o disminuye el número de líneas, se asusta un poco. Como puede haber visto en el complemento de tamaño automático para jQuery, lo solucionan clonando el área de texto, estableciendo su altura en auto en lugar del original, y luego usándolo para establecer la altura de desplazamiento en el original. Lo hice en este violín actualizado: jsfiddle.net/CbqFv/2 Resuelve el problema de IE pero Firefox deja de funcionar.
Chris Moschini

3
@HelenNeely: Entonces no uses una identificación. Por ejemplo, use una clase y haga lo que init hace para todos los elementos de esa clase. Esa debería ser una tarea para principiantes.
panzi

3
@ DenilsonSá Si uno pudiera asumir que solo se utilizan navegadores modernos, la web sería un lugar mejor.
panzi

2
Esto no funcionará bien si una barra de desplazamiento está envuelta en IE11. Si usa este violín jsfiddle.net/CbqFv e ingresa líneas hasta que tenga una barra de desplazamiento, lo verá. ¿Algunas ideas?
kaljak

66
Esto se rompe por completo si el área de texto está cerca del final de la página inferior; todo salta hacia adelante y hacia atrás debido a style.height='auto'. Sospecho que la solución es agregar un hermano oculto utilizado solo para la medición.
rr-

372

UNA SOLUCIÓN COMPLETA Y SIMPLE

2020-05-14 actualizado (Soporte de navegador mejorado para móviles y tabletas)

El siguiente código funcionará:

  • En entrada clave.
  • Con texto pegado (clic derecho y ctrl + v).
  • Con texto cortado (clic derecho y ctrl + x).
  • Con texto precargado.
  • Con todos los sitios de textarea (cuadros de texto de varias líneas) en todo el sitio.
  • Con Firefox (v31-67 probado).
  • Con Chrome (v37-74 probado).
  • Con IE (v9-v11 probado).
  • Con Edge (v14-v18 probado).
  • Con IOS Safari .
  • Con el navegador de Android .
  • Con modo estricto de JavaScript .
  • Está validado w3c .
  • Y es aerodinámico y eficiente.

OPCIÓN 1 (Con jQuery)

Esta opción requiere jQuery y se ha probado y funciona con 1.7.2 - 3.3.1

Simple (Agregue este código jquery a su archivo de script maestro y olvídese).

$('textarea').each(function () {
  this.setAttribute('style', 'height:' + (this.scrollHeight) + 'px;overflow-y:hidden;');
}).on('input', function () {
  this.style.height = 'auto';
  this.style.height = (this.scrollHeight) + 'px';
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<textarea placeholder="Type, paste, cut text here...">PRELOADED TEXT.
This javascript should now add better support for IOS browsers and Android browsers.</textarea>
<textarea placeholder="Type, paste, cut text here..."></textarea>

Test on jsfiddle


OPCIÓN 2 (JavaScript puro)

Simple (Agregue este JavaScript a su archivo de script maestro y olvídese de él).

const tx = document.getElementsByTagName('textarea');
for (let i = 0; i < tx.length; i++) {
  tx[i].setAttribute('style', 'height:' + (tx[i].scrollHeight) + 'px;overflow-y:hidden;');
  tx[i].addEventListener("input", OnInput, false);
}

function OnInput() {
  this.style.height = 'auto';
  this.style.height = (this.scrollHeight) + 'px';
}
<textarea placeholder="Type, paste, cut text here...">PRELOADED TEXT. This JavaScript should now add better support for IOS browsers and Android browsers.</textarea>
<textarea placeholder="Type, paste, cut text here..."></textarea>

Test on jsfiddle


OPCIÓN 3 (extensión jQuery)

Útil si desea aplicar más encadenamiento a las áreas de texto que desea ajustar automáticamente.

jQuery.fn.extend({
  autoHeight: function () {
    function autoHeight_(element) {
      return jQuery(element)
        .css({ 'height': 'auto', 'overflow-y': 'hidden' })
        .height(element.scrollHeight);
    }
    return this.each(function() {
      autoHeight_(this).on('input', function() {
        autoHeight_(this);
      });
    });
  }
});

Invocar con $('textarea').autoHeight()


ACTUALIZAR TEXTAREA A TRAVÉS DE JAVASCRIPT

Al inyectar contenido en un área de texto a través de JavaScript, agregue el siguiente código para invocar la función en la opción 1.

$('textarea').trigger('input');

ALTURA DE TEXTAREA PREDETERMINADA

Para corregir la altura inicial del área de texto, deberá agregar una condición adicional:

const txHeight = 16;
const tx = document.getElementsByTagName("textarea");
for (let i = 0; i < tx.length; i++) {
  if (tx[i].value == '') {
    tx[i].setAttribute("style", "height:" + txHeight + "px;overflow-y:hidden;");
  } else {
    tx[i].setAttribute("style", "height:" + (tx[i].scrollHeight) + "px;overflow-y:hidden;");
  }
  tx[i].addEventListener("input", OnInput, false);
}

function OnInput(e) {
  this.style.height = "auto";
  this.style.height = (this.scrollHeight) + "px";
}
<textarea placeholder="Type, paste, cut text here...">PRELOADED TEXT. This JavaScript should now add better support for IOS browsers and Android browsers.</textarea>
<textarea placeholder="Type, paste, cut text here..."></textarea>


12
Esta es una gran solución, sería un poco más comprensible si el nombre del método y el nombre del parámetro se actualizaran para ser nombres verdaderos en lugar de letras individuales.
Chris Marisic

55
@Obsidian ¡Gracias! Me acabo de dar cuenta de por qué siempre obtengo un 0: ¡puse el área de texto en un modo Bootstrap! Como el modal está oculto al principio, el área de texto tendrá 0 scrollHeight 😂😂
WTIFS

77
@Obsidian Fantastic !! (Opción 3). El this.style.height = 'auto';es el arreglo de comportamiento mágico. Estaba tan frustrado por qué el scrollHeight tenía un comportamiento tan extraño. La altura a automática, luego haciendo coincidir la altura de desplazamiento en el mismo ciclo de renderizado, todavía me sorprende cómo "soluciona" este problema, aunque solo debería estar técnicamente pintando la segunda altura.
bit bit

2
Probé la opción 3 en Chrome hoy y tuve que hacer un par de ajustes. 1) No siempre cambiará el tamaño correctamente si tiene una transición de "altura" o "todo" en el área de texto. Recomiendo no usar transiciones que afecten la altura. 2) El scrollHeight estaba devolviendo un mínimo de dos filas de altura (quizás porque ese es el valor predeterminado para las áreas de texto en Chrome) pero si cambia this.style.height = 'auto'; to this.style.height = '0px'; y agregue una altura mínima para evitar que el estado inicial realmente llegue a 0, scrollHeight devolverá correctamente una fila de altura cuando sea apropiado.
ZorroDeLaArena

3
@Obsidian ¿Puede explicar cómo this.style.height = 'auto';corrige el comportamiento de scrollHeight? Es solo magia.
sidney

63

La solución jQuery ajusta el CSS para que coincida con sus requisitos

css ...

div#container textarea {
    min-width: 270px;
    width: 270px;
    height: 22px;
    line-height: 24px;
    min-height: 22px;
    overflow-y: hidden; /* fixes scrollbar flash - kudos to @brettjonesdev */
    padding-top: 1.1em; /* fixes text jump on Enter keypress */
}

javascript ...

// auto adjust the height of
$('#container').delegate( 'textarea', 'keydown', function (){
    $(this).height( 0 );
    $(this).height( this.scrollHeight );
});
$('#container').find( 'textarea' ).keydown();

O alternativa para jQuery 1.7 + ...

// auto adjust the height of
$('#container').on( 'keyup', 'textarea', function (){
    $(this).height( 0 );
    $(this).height( this.scrollHeight );
});
$('#container').find( 'textarea' ).keyup();

He creado un violín con el estilo mínimo absoluto como punto de partida para sus experimentos ... http://jsfiddle.net/53eAy/951/


55
Esto es bueno, pero agregaría overflow-y: hidden;al CSS para evitar que la barra de desplazamiento parpadee brevemente cuando se produce el cambio de tamaño.
brettjonesdev

No del todo seguro, pero sin él el área de texto crece demasiado. Creo que tiene que ver con la forma en que se calculan los elementos scrollHeight.
chim

1
Use múltiples eventos para hacer el trabajo para una gran variedad de escenarios $('textarea.auto-resize').on('change cut paste drop keyup', function(){...})
Raxith

1
Salta como loco en Chrome 40 Win 8.1 en textos más largos que la ventana gráfica. Lo hace bastante inutilizable.
tobibeer

1
Mantener enter (nueva línea) da como resultado el desplazamiento. El tamaño no se ajusta hasta que se suelta la tecla.
Niels Abildgaard

28
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Textarea autoresize</title>
    <style>
    textarea {
        overflow: hidden;
    }
    </style>
    <script>
    function resizeTextarea(ev) {
        this.style.height = '24px';
        this.style.height = this.scrollHeight + 12 + 'px';
    }

    var te = document.querySelector('textarea');
    te.addEventListener('input', resizeTextarea);
    </script>
</head>
<body>
    <textarea></textarea>
</body>
</html>

Probado en Firefox 14 y Chromium 18. Los números 24 y 12 son arbitrarios, prueba para ver cuál te queda mejor.

Podría prescindir de las etiquetas de estilo y script, pero se vuelve un poco desordenado en mi humilde opinión (este es HTML + JS de estilo antiguo y no se recomienda).

<textarea style="overflow: hidden" onkeyup="this.style.height='24px'; this.style.height = this.scrollHeight + 12 + 'px';"></textarea>

Editar: código modernizado. Se cambió el atributo onkeyup a addEventListener.
Editar: keydown funciona mejor que keyup
Editar: declarar la función antes de usar
Editar: la entrada funciona mejor que keydown (thnx @ WASD42 y @ MA-Maddin)

jsfiddle


3
Este tiene algunos inconvenientes: 1) Textarea no se cambiaría de tamaño y el usuario pegaría algo solo con los botones del mouse; 2) Si el usuario pega algo usando el teclado (Ctrl + V), el área de texto se redimensionará solo cuando suelte Ctrl. Si el usuario presiona Ctrl + V varias veces, el área de texto crecerá solo después de la última. También debe agregar la misma función para pegar, cortar, cambiar y soltar eventos.
WASD42

Así que solo usa el inputevento en su lugar. Ver stackoverflow.com/a/14029861/1951524
Martin Schneider el

Versión mejorada con textareasoporte múltiple de una sola línea:document.querySelectorAll('textarea').forEach(function(te){ te.addEventListener("input", function() { this.style.height='24px'; this.style.height=this.scrollHeight+12+'px'; }); });
Meisner

1
@Meisner Es más corto, pero no diría que está "mejorado". Con una función anónima, no hay forma de llamar removeEventListenery limpiar sus oyentes de eventos. Esto es especialmente importante cuando se crean oyentes de eventos por todo el lugar en un bucle forEach. Además, en mi opinión, la legibilidad es mucho más importante que la concisión.
GijsjanB

para otros y para mí en el futuro, asegúrese de que la box-sizing: border-box;propiedad esté establecida o de lo contrario, el área de texto explica 4px para cada evento onInput. Pasé como 3 horas hasta que descubrí que este era el problema.
partir del

24

La mejor solución (funciona y es corta) para mí es:

    $(document).on('input', 'textarea', function () {
        $(this).outerHeight(38).outerHeight(this.scrollHeight); // 38 or '1em' -min-height
    }); 

Funciona a la perfección sin parpadear con pegar (con el mouse también), cortar, ingresar y se contrae al tamaño correcto.

Por favor, eche un vistazo a jsFiddle .


¡¡¡Estupendo!!! un trato de línea! pregunta tonta ¿Cómo puedo agregar una animación cuando cambia el tamaño? como que el cuadro de texto cambia de tamaño suavemente en lugar del salto al tamaño?
user2513846

1
@ user2513846 Parece que no es posible mediante el diseño de edición de varias líneas. Hice un ejemplo de animar el tamaño del área de texto: jsfiddle.net/yk2g333e Como saben, el cursor de texto baja en el y de la línea o el cursor, así que si no hay pausa en este momento, no hay nada que animar. Pero la pausa será muy molesta para el usuario.
vatavale

1
@ user2513846 Sin embargo, con una línea vacía más al final del área de texto, es posible tener una animación fluida: jsfiddle.net/p23erdfr
vatavale

16

Está utilizando el valor más alto de la actual clientHeight y el contenido scrollHeight. Cuando hace que scrollHeight sea más pequeño al eliminar contenido, el área calculada no puede reducirse porque clientHeight, previamente establecido por style.height, lo mantiene abierto. En su lugar, puede tomar un máximo () de scrollHeight y un valor de altura mínima que haya predefinido o calculado a partir de textarea.rows.

En general, probablemente no debería confiar en scrollHeight en los controles de formulario. Además de que scrollHeight es tradicionalmente menos compatible que algunas de las otras extensiones de IE, HTML / CSS no dice nada acerca de cómo se implementan los controles de formulario internamente y no se garantiza que scrollHeight sea algo significativo. (Tradicionalmente, algunos navegadores han utilizado widgets del sistema operativo para la tarea, lo que hace imposible la interacción CSS y DOM en sus componentes internos). Al menos olfatee la existencia de scrollHeight / clientHeight antes de intentar habilitar el efecto.

Otro posible enfoque alternativo para evitar el problema si es importante que funcione más ampliamente podría ser usar un div oculto con el mismo ancho que el área de texto y establecerlo en la misma fuente. En el keyup, copia el texto del área de texto a un nodo de texto en div oculto (recordando reemplazar '\ n' con un salto de línea, y escapa '' '' 'correctamente' si está utilizando innerHTML). Luego, simplemente midiendo el desplazamiento del div, la altura le dará la altura que necesita.


1
¿Con qué navegadores se supone que tienen problemas scrollHeightpara las áreas de texto? Funciona bien con las versiones actuales de IE, Firefox y Opera ...
Christoph

1
El único que tengo a mano es Konqueror, que devuelve el clientHeight como scrollHeight. Este es un comportamiento que puede esperar a menos que el navegador aplique el modelo de cuadro CSS a los componentes internos de los widgets, algo que no siempre han hecho y el estándar no dice que tengan que hacerlo.
bobince

14

Si no necesita admitir IE8, puede usar el inputevento:

var resizingTextareas = [].slice.call(document.querySelectorAll('textarea[autoresize]'));

resizingTextareas.forEach(function(textarea) {
  textarea.addEventListener('input', autoresize, false);
});

function autoresize() {
  this.style.height = 'auto';
  this.style.height = this.scrollHeight+'px';
  this.scrollTop = this.scrollHeight;
  window.scrollTo(window.scrollLeft,(this.scrollTop+this.scrollHeight));
}

Ahora solo necesita agregar un poco de CSS y ya está:

textarea[autoresize] {
  display: block;
  overflow: hidden;
  resize: none;
}

Uso:

<textarea autoresize>Type here and Ill resize.</textarea>

Puedes leer más sobre cómo funciona en mi blog .


1
Buena solución, pero necesita poca solución. Cuando se carga el contenido de textarea f.ex. de la base de datos, el área de texto se mantiene pequeña. Debe activar el inputevento durante la inicialización en cada ciclo.
Ajax

11

tamaño automático

https://github.com/jackmoore/autosize

Just works, independiente, es popular (3.0k + estrellas GitHub a partir de octubre de 2018), disponible en cdnjs ) y ligero (~ 3.5k). Manifestación:

<textarea id="autosize" style="width:200px;">a
J   b
c</textarea>
<script src="https://cdnjs.cloudflare.com/ajax/libs/autosize.js/4.0.2/autosize.min.js"></script>
<script>autosize(document.querySelectorAll('#autosize'));</script>

Por cierto, si está utilizando el editor ACE, use maxLines: Infinity: Ajusta automáticamente la altura a los contenidos en el editor Ace Cloud 9


2
La versión 2 se lanzó en febrero de 2015. Se ha vuelto más simple y ya no depende de jQuery
crujiente el

Lo siento, funciona. Tal vez estaba en otro navegador ... así que creo que es mejor si ignoras mi comentario ...
Toni Michel Caubet

@ToniMichelCaubet ah, OK, tal vez un problema de CDN entonces. Dejame revisar.
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

El autosizecomplemento no permite cambiar el tamaño manualmente usando el icono de cambio de tamaño en textarea.
j4v1

7

Encontré un trazador de líneas desde aquí ;

<textarea name="text" oninput="this.style.height = ''; this.style.height = this.scrollHeight +'px'"></textarea>

6

¿Alguien ha considerado contento? No pierda el tiempo con el desplazamiento, y el único JS que me gusta es si planea guardar los datos en el desenfoque ... y aparentemente, es compatible en todos los navegadores populares: http://caniuse.com/#feat = contentable

Simplemente dale estilo para que parezca un cuadro de texto, y se ajusta automáticamente ... Haz que su altura mínima sea la altura de texto preferida y tenlo.

Lo bueno de este enfoque es que puede guardar y etiquetar en algunos de los navegadores.

http://jsfiddle.net/gbutiri/v31o8xfo/

<style>
.autoheight {
    min-height: 16px;
    font-size: 16px;
    margin: 0;
    padding: 10px;
    font-family: Arial;
    line-height: 16px;
    box-sizing: border-box;
    -moz-box-sizing: border-box;
    -webkit-box-sizing: border-box;
    overflow: hidden;
    resize: none;
    border: 1px solid #ccc;
    outline: none;
    width: 200px;
}
</style>
<script src="https://code.jquery.com/jquery-2.1.1.min.js"></script>
<script>
$(document).on('blur','.autoheight',function(e) {
    var $this = $(this);
    // The text is here. Do whatever you want with it.
    console.log($this.html());
});

</script>
<div class="autoheight contenteditable" contenteditable="true">Mickey Mouse</div>

Chrome agregará elementos <div> en ENTER.
sbaechler

contenteditablees bueno, pero si quieres texto sin formato necesita un montón de opciones como -webkit-user-modify: read-write-plaintext-onlyy white-space: pre-wrap.
mik01aj

@_sbaechler: los <div> s se omiten al usar [dom-element].innerText. @WebmasterG En mi humilde opinión, sería bueno omitir jquery (por transparencia) e incluir el ejemplo en esta página a través de Fragmento de código ejecutable en lugar de en jsfiddle.
adabru

4

Usé el siguiente código para múltiples áreas de texto. Funciona bien en Chrome 12, Firefox 5 e IE 9, incluso con las acciones de eliminar, cortar y pegar realizadas en las áreas de texto.

<!-- language: lang-html -->
<style type='text/css'>
textarea { border:0 none; overflow:hidden; outline:none; background-color:#eee }
</style>
<textarea style='height:100px;font-family:arial' id="txt1"></textarea>
<textarea style='height:125px;font-family:arial' id="txt2"></textarea>
<textarea style='height:150px;font-family:arial' id="txt3"></textarea>
<textarea style='height:175px;font-family:arial' id="txt4"></textarea>
<script type='text/javascript'>
function attachAutoResizeEvents()
{   for(i=1;i<=4;i++)
    {   var txtX=document.getElementById('txt'+i)
        var minH=txtX.style.height.substr(0,txtX.style.height.indexOf('px'))
        txtX.onchange=new Function("resize(this,"+minH+")")
        txtX.onkeyup=new Function("resize(this,"+minH+")")
        txtX.onchange(txtX,minH)
    }
}
function resize(txtX,minH)
{   txtX.style.height = 'auto' // required when delete, cut or paste is performed
    txtX.style.height = txtX.scrollHeight+'px'
    if(txtX.scrollHeight<=minH)
        txtX.style.height = minH+'px'
}
window.onload=attachAutoResizeEvents
</script>

4

Hay un enfoque ligeramente diferente.

<div style="position: relative">
  <pre style="white-space: pre-wrap; word-wrap: break-word"></pre>
  <textarea style="position: absolute; top: 0; left: 0; width: 100%; height: 100%"></textarea>
</div>

La idea es copiar el texto desde textareadentro de la prey dejar CSS asegurarse de que tienen el mismo tamaño.

El beneficio es que los marcos presentan herramientas simples para mover el texto sin tocar ningún evento. A saber, en AngularJS agregarías un ng-model="foo" ng-trim="false"a textareay ng-bind="foo + '\n'"al pre. Ver un violín .

Solo asegúrese de que pretenga el mismo tamaño de fuente que textarea.


1
" Solo asegúrese de que pretenga el mismo tamaño de fuente que eltextarea " - Necesitan lo mismo line-height, y una cantidad igual de paddingy / o bordertambién. Esta es la mejor solución para Angular.
Jamie Barker

4

Lo siguiente funciona para cortar, pegar, etc., independientemente de si esas acciones son del mouse, un atajo de teclado, seleccionando una opción de una barra de menú ... varias respuestas tienen un enfoque similar pero no tienen en cuenta el cuadro- dimensionamiento, por lo que aplican incorrectamente el estilo overflow: hidden.

Hago lo siguiente, que también funciona bien con max-heighty rowspara la altura mínima y máxima.

function adjust() {
  var style = this.currentStyle || window.getComputedStyle(this);
  var boxSizing = style.boxSizing === 'border-box'
      ? parseInt(style.borderBottomWidth, 10) +
        parseInt(style.borderTopWidth, 10)
      : 0;
  this.style.height = '';
  this.style.height = (this.scrollHeight + boxSizing) + 'px';
};

var textarea = document.getElementById("ta");
if ('onpropertychange' in textarea) { // IE
  textarea.onpropertychange = adjust;
} else if ('oninput' in textarea) {
  textarea.oninput = adjust;
}
setTimeout(adjust.bind(textarea));
textarea {
  resize: none;
  max-height: 150px;
  border: 1px solid #999;
  outline: none;
  font: 18px sans-serif;
  color: #333;
  width: 100%;
  padding: 8px 14px;
  box-sizing: border-box;
}
<textarea rows="3" id="ta">
Try adding several lines to this.
</textarea>

Para completar por completo, debe llamar a la adjustfunción en algunas circunstancias más:

  1. Eventos de cambio de tamaño de ventana, si el ancho de los textareacambios con el cambio de tamaño de la ventana u otros eventos que cambian el ancho del área de texto
  2. Cuando el textarea's displaycambios de atributos de estilo, por ejemplo, cuando pasa de none(oculto) ablock
  3. Cuando el valor de la textarease cambia programáticamente

Tenga en cuenta que usar window.getComputedStyleu obtener currentStylepuede ser algo costoso desde el punto de vista computacional, por lo que es posible que desee almacenar en caché el resultado.

Funciona para IE6, así que realmente espero que sea un soporte lo suficientemente bueno.


4

Como un enfoque diferente, puede usar un <span>que ajusta su tamaño automáticamente. Deberá hacerlo editable agregando la contenteditable="true"propiedad y listo:

div {
  width: 200px;
}

span {
  border: 1px solid #000;
  padding: 5px;
}
<div>
  <span contenteditable="true">This text can be edited by the user</span>
</div>

El único problema con este enfoque es que si desea enviar el valor como parte del formulario, deberá hacerlo usted mismo en JavaScript. Hacerlo es relativamente fácil. Por ejemplo, puede agregar un campo oculto y, en onsubmitcaso de que el formulario se asigne, el valor del spancampo oculto se enviará automáticamente con el formulario.


Ya hay una respuesta usando contenteditable en esta página: stackoverflow.com/questions/454202/…
adabru

@adabru Sí, pero las dos respuestas no son las mismas. Toyota hace autos rojos, y Ford también hace autos rojos, pero son diferentes, ¿no? Si te gusta más la otra respuesta, entonces ve con ella. Pero hay quienes aprecian más mi respuesta y van con ella. Tener diferentes opciones es bueno.
Racil Hilan

3

Un poco de correcciones. Funciona perfectamente en Opera

  $('textarea').bind('keyup keypress', function() {
      $(this).height('');
      var brCount = this.value.split('\n').length;
      this.rows = brCount+1; //++ To remove twitching
      var areaH = this.scrollHeight,
          lineHeight = $(this).css('line-height').replace('px',''),
          calcRows = Math.floor(areaH/lineHeight);
      this.rows = calcRows;
  });

funciona siempre que sus líneas no se desborden, entonces no encajarán.
Tomáš Kafka

funciona de fábrica, genial (firefox 72)
Mikeys4u

2

Conozco una forma corta y correcta de implementar esto con jquery. No se necesita div oculto adicional y funciona en la mayoría de los navegadores

<script type="text/javascript">$(function(){
$("textarea").live("keyup keydown",function(){
var h=$(this);
h.height(60).height(h[0].scrollHeight);//where 60 is minimum height of textarea
});});

</script>

jQuery's .live()ha quedado en desuso. api.jquery.com/live En general, querrá usar .on()en su lugar.
Lucas

2

No sé si alguien lo menciona de esta manera, pero en algunos casos es posible cambiar el tamaño de la altura con filas.

textarea.setAttribute('rows',breaks);

Manifestación


1
Eso funciona solo si tienes white-space: nowrap;. Cuando una línea se ajusta a otra línea sin salto de línea, el área de texto ya no se ajustará correctamente.
Yeti

2

Aquí hay una directiva angularjs para la respuesta de panzi.

 module.directive('autoHeight', function() {
        return {
            restrict: 'A',
            link: function(scope, element, attrs) {
                element = element[0];
                var resize = function(){
                    element.style.height = 'auto';
                    element.style.height = (element.scrollHeight)+'px';
                };
                element.addEventListener('change', resize, false);
                element.addEventListener('cut',    resize, false);
                element.addEventListener('paste',  resize, false);
                element.addEventListener('drop',   resize, false);
                element.addEventListener('keydown',resize, false);

                setTimeout(resize, 100);
            }
        };
    });

HTML:

<textarea ng-model="foo" auto-height></textarea>

Debería usar $ timeout en lugar de setTimout; esto asegurará que el modelo se inicialice (no es necesario especificar milisegundos; se ejecutará después del ciclo de digestión angular). También elemento = elemento [0]; es una muy mala práctica ... De todos modos, la solución no es buena para mí, ya que necesito que el área de texto sea de una línea hasta que haya más texto.
Karol Websky

2

Puede usar JQuery para expandir textareamientras escribe:

$(document).find('textarea').each(function () {
  var offset = this.offsetHeight - this.clientHeight;

  $(this).on('keyup input focus', function () {
    $(this).css('height', 'auto').css('height', this.scrollHeight + offset);
  });
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<div>
<textarea name="note"></textarea>
<div>


Solución más limpia. pero como deberíamos dejar de usar jQuery: textarea.addEventListener ('keyup', () => {textarea.style.height = 0; textarea.style.height = ${textarea.scrollHeight}px;});
Toni Michel Caubet

2

Aquellos que quieran lograr lo mismo en nuevas versiones de Angular.

Toma textArea elementRef.

@ViewChild('textArea', { read: ElementRef }) textArea: ElementRef;

public autoShrinkGrow() {
    textArea.style.overflow = 'hidden';
    textArea.style.height = '0px';
    textArea.style.height = textArea.scrollHeight + 'px';
}

<textarea (keyup)="autoGrow()" #textArea></textarea>

También estoy agregando otro caso de uso que puede ser útil para algunos usuarios que leen el hilo, cuando el usuario desea aumentar la altura del área de texto a cierta altura y luego tenerlo overflow:scroll, el método anterior se puede extender para lograr el caso de uso mencionado.

  public autoGrowShrinkToCertainHeight() {
    const textArea = this.textArea.nativeElement;
    if (textArea.scrollHeight > 77) {
      textArea.style.overflow = 'auto';
      return;
    }
    else {
      textArea.style.overflow = 'hidden';
      textArea.style.height = '0px';
      textArea.style.height = textArea.scrollHeight + 'px';
    }
  }

1

Algunas de las respuestas aquí no tienen en cuenta el relleno.

Suponiendo que tiene una altura máxima que no desea superar, esto funcionó para mí:

    // obviously requires jQuery

    // element is the textarea DOM node

    var $el = $(element);
    // inner height is height + padding
    // outerHeight includes border (and possibly margins too?)
    var padding = $el.innerHeight() - $el.height();
    var originalHeight = $el.height();

    // XXX: Don't leave this hardcoded
    var maxHeight = 300;

    var adjust = function() {
        // reset it to the original height so that scrollHeight makes sense
        $el.height(originalHeight);

        // this is the desired height (adjusted to content size)
        var height = element.scrollHeight - padding;

        // If you don't want a maxHeight, you can ignore this
        height = Math.min(height, maxHeight);

        // Set the height to the new adjusted height
        $el.height(height);
    }

    // The input event only works on modern browsers
    element.addEventListener('input', adjust);

1

Un enfoque aún más simple y limpio es este:

// adjust height of textarea.auto-height
$(document).on( 'keyup', 'textarea.auto-height', function (e){
    $(this).css('height', 'auto' ); // you can have this here or declared in CSS instead
    $(this).height( this.scrollHeight );
}).keyup();

// y el CSS

textarea.auto-height {
    resize: vertical;
    max-height: 600px; /* set as you need it */
    height: auto;      /* can be set here of in JS */
    overflow-y: auto;
    word-wrap:break-word
}

Todo lo que se necesita es agregar la .auto-heightclase a cualquiera textareaque desee apuntar.

Probado en FF, Chrome y Safari. Avíseme si esto no funciona para usted, por alguna razón. Pero, esta es la forma más limpia y simple en que he encontrado que esto funciona. ¡Y funciona muy bien! :RE


¿Intentaste eliminar el texto después de editarlo? ¿Se colapsó el área de texto?
18C

1

Este código funciona para pegar y seleccionar eliminar también.

onKeyPressTextMessage = function(){
			var textArea = event.currentTarget;
    	textArea.style.height = 'auto';
    	textArea.style.height = textArea.scrollHeight + 'px';
};
<textarea onkeyup="onKeyPressTextMessage(event)" name="welcomeContentTmpl" id="welcomeContent" onblur="onblurWelcomeTitle(event)" rows="2" cols="40" maxlength="320"></textarea>

Aquí está el JSFiddle


1

Recomiendo la biblioteca javascript de http://javierjulio.github.io/textarea-autosize .

Por comentarios, agregue codeblock de ejemplo sobre el uso del complemento:

<textarea class="js-auto-size" rows="1"></textarea>

<script src="http://code.jquery.com/jquery-2.1.0.min.js"></script>
<script src="jquery.textarea_autosize.min.js"></script>
<script>
$('textarea.js-auto-size').textareaAutoSize();
</script>

CSS mínimo requerido:

textarea {
  box-sizing: border-box;
  max-height: 160px; // optional but recommended
  min-height: 38px;
  overflow-x: hidden; // for Firefox (issue #5)
}

1

MakeTextAreaResisable que usa qQuery

function MakeTextAreaResisable(id) {
    var o = $(id);
    o.css("overflow-y", "hidden");

    function ResizeTextArea() {
        o.height('auto');
        o.height(o[0].scrollHeight);
    }

    o.on('change', function (e) {
        ResizeTextArea();
    });

    o.on('cut paste drop keydown', function (e) {
        window.setTimeout(ResizeTextArea, 0);
    });

    o.focus();
    o.select();
    ResizeTextArea();
}


1

mi implementación es muy simple, cuente el número de líneas en la entrada (y un mínimo de 2 filas para mostrar que es un área de texto):

textarea.rows = Math.max(2, textarea.value.split("\n").length) // # oninput

ejemplo de trabajo completo con estímulo: https://jsbin.com/kajosolini/1/edit?html,js,output

(y esto funciona con el controlador de cambio de tamaño manual del navegador, por ejemplo)


2
Esto solo funciona si rompe la línea presionando "enter". Si su texto es más largo que el ancho del área de texto pero no presiona "enter", no se expande.
Nathalia Xavier

1

La respuesta aceptada funciona bien. Pero eso es mucho código para esta funcionalidad simple. El siguiente código hará el truco.

   $(document).on("keypress", "textarea", function (e) {
    var height = $(this).css("height");
    var iScrollHeight = $(this).prop("scrollHeight");
    $(this).css('height',iScrollHeight);
    });

0

Esto es lo que hice mientras usaba MVC HTML Helper para TextArea. Tenía bastantes elementos de área de texto, así que tuve que distinguirlos usando Id de modelo.

 @Html.TextAreaFor(m => m.Text, 2, 1, new { id = "text" + Model.Id, onkeyup = "resizeTextBox(" + Model.Id + ");" })

y en script agregó esto:

   function resizeTextBox(ID) {            
        var text = document.getElementById('text' + ID);
        text.style.height = 'auto';
        text.style.height = text.scrollHeight + 'px';            
    }

Lo he probado en IE10 y Firefox23


0

Puedes usar este código:

Coffescript:

jQuery.fn.extend autoHeightTextarea: ->
  autoHeightTextarea_ = (element) ->
    jQuery(element).css(
      'height': 'auto'
      'overflow-y': 'hidden').height element.scrollHeight

  @each ->
    autoHeightTextarea_(@).on 'input', ->
      autoHeightTextarea_ @

$('textarea_class_or_id`').autoHeightTextarea()

Javascript

jQuery.fn.extend({
  autoHeightTextarea: function() {
    var autoHeightTextarea_;
    autoHeightTextarea_ = function(element) {
      return jQuery(element).css({
        'height': 'auto',
        'overflow-y': 'hidden'
      }).height(element.scrollHeight);
    };
    return this.each(function() {
      return autoHeightTextarea_(this).on('input', function() {
        return autoHeightTextarea_(this);
      });
    });
  }
});

$('textarea_class_or_id`').autoHeightTextarea();
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.