Expandir automáticamente un área de texto usando jQuery

128

¿Cómo puedo hacer que un área de texto se expanda automáticamente usando jQuery?

Tengo un cuadro de texto para explicar la agenda de la reunión, por lo que quiero ampliar ese cuadro de texto cuando el texto de mi agenda siga creciendo en esa área.

Piyush
fuente
i thik textarea es autoexpandible.
Andrew Sullivan
Considere cambiar su pregunta y eliminar la palabra "jQuery"
vsync

Respuestas:

113

He intentado mucho y este es genial. Link está muerto. La versión más nueva está disponible aquí . Vea a continuación la versión anterior.
Puede intentar presionando y manteniendo presionada la tecla Intro en el área de texto. Compare el efecto con el otro complemento textarea de expansión automática ...

editar basado en comentario

$(function() {
   $('#txtMeetingAgenda').autogrow();
});

nota: debe incluir los archivos js necesarios ...

Para evitar que la barra de desplazamiento en el área de texto parpadee durante la expansión / contracción, también puede configurarlo overflowen hidden:

$('#textMeetingAgenda').css('overflow', 'hidden').autogrow()




Actualizar:

El enlace de arriba está roto. Pero aún puede obtener los archivos javascript aquí .

Reigel
fuente
si mi cuadro de texto ID es txtMeetingAgenda entonces ¿Puedo implementar la propiedad Auto caja de texto en jQuery
Piyush
aquí haga clic en el evento está definido o no
Piyush
Esto es todo sobre textarea, pero ¿qué pasa con textbox? ¿Este complemento también funciona para textbox?
Piyush
1
este complemento no funciona bien, prueba el tamaño automático, es mucho mejor
julesbou
Funciona bien solo de una manera cuando textarea está creciendo. Pero cuando comienza a eliminar el texto, no se reduce automáticamente la altura.
Ekashking
166

Si no quieres un complemento, hay una solución muy simple

$("textarea").keyup(function(e) {
    while($(this).outerHeight() < this.scrollHeight + parseFloat($(this).css("borderTopWidth")) + parseFloat($(this).css("borderBottomWidth"))) {
        $(this).height($(this).height()+1);
    };
});

Véalo trabajando en un jsFiddle Solía ​​responder otra pregunta de textarea aquí .

Para responder a la pregunta de hacerlo a la inversa o hacerlo más pequeño a medida que se elimina el texto: jsFiddle

Y si quieres un complemento

@ Jason ha diseñado uno aquí

SpYk3HH
fuente
1
Tuve que eliminar + parseFloat ($ (this) .css ("borderTopWidth")) + parseFloat ($ (this) .css ("borderBottomWidth")), de lo contrario, se repite infinitamente con un área de texto diseñada con bootstrap
blacelle
3
Versión jQuery-less:if (this.clientHeight < this.scrollHeight) { this.style.height = this.scrollHeight + 'px'; }
Georgii Ivankin
3
@metakungfu Bueno, en lugar de solo votar negativamente, tal vez puedas ayudar a mejorar la respuesta. No tengo ninguna forma de probar el cajero automático de Apple y el safari para Windows se suspendió hace mucho tiempo. Así que realmente no puedo hacer nada para determinar por qué no funcionaría. En cuanto al código, no hay nada de malo en esta solución. ¿Estás seguro de que es el código el que se rompe y no el safari que se rompe en jsfiddle? Safari es bastante exigente y Fiddle acaba de pasar por una actualización importante. Mayeb puede abrir dev con y proporcionar más detalles?
SpYk3HH
1
También necesita área de texto conjunto desbordamiento-y a escondidas para evitar parpadear desplazamiento
iulial
2
Si deseo eliminar las filas agregadas, el tamaño ampliado del cuadro de texto sigue siendo el mismo, ¿es posible que también pueda cambiar el tamaño automáticamente?
Steven
33

Crece / encoge el área de texto. Esta demostración utiliza jQuery para el enlace de eventos, pero no es imprescindible de ninguna manera.
( sin compatibilidad con IE: IE no responde al cambio de atributo de filas )

PAGINA DEMO


HTML

<textarea class='autoExpand' rows='3' data-min-rows='3' placeholder='Auto-Expanding Textarea'></textarea>

CSS

textarea{  
  display:block;
  box-sizing: padding-box;
  overflow:hidden;

  padding:10px;
  width:250px;
  font-size:14px;
  margin:50px auto;
  border-radius:8px;
  border:6px solid #556677;
}

javascript (actualizado)

$(document)
    .one('focus.textarea', '.autoExpand', function(){
        var savedValue = this.value;
        this.value = '';
        this.baseScrollHeight = this.scrollHeight;
        this.value = savedValue;
    })
    .on('input.textarea', '.autoExpand', function(){
        var minRows = this.getAttribute('data-min-rows')|0,
            rows;
        this.rows = minRows;
        rows = Math.ceil((this.scrollHeight - this.baseScrollHeight) / 16);
        this.rows = minRows + rows;
    });
vsync
fuente
2
porque el código debe esperar un poco para que la letra que escribió se imprima dentro del área de texto y, por lo tanto, cambie las dimensiones del área de texto
vsync
1
Ya veo, la solución se rompe cuando el texto se copia (CTRL + V) de cualquier fuente. Si bien, si el texto se escribe manualmente, esto es increíble y muy suave.
Satya Kalluri
1
@vsync: ¿cómo modificaría para múltiples áreas de texto? ¿Tienes textarea1 y textarea2 y quieres permitir que ambos crezcan?
jmoreno
1
¡Esta debería ser la mejor respuesta! Publiqué una pregunta basada en eso si alguien está interesado: stackoverflow.com/questions/29930300/…
gsamaras
1
@AllyMurray - Fui ahora y lo actualicé a 16 ya que parece dar un mejor resultado. y sí, esa es la altura de línea esperada
vsync
20

Puedes probar este

$('#content').on('change keyup keydown paste cut', 'textarea', function () {
        $(this).height(0).height(this.scrollHeight);
    }).find('textarea').change();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="content">
  <textarea>How about it</textarea><br />
  <textarea rows="5">111111
222222
333333
444444
555555
666666</textarea>
</div>

reza.cse08
fuente
si desea obtener el scrollHeight de $ (this), puede usar $ (this) .prop ('scrollHeight'); en cambio;)
Samuel Vicent
3
parpadea cada salto de línea
Joe
11

Gracias a SpYk3HH, comencé con su solución y la convertí en esta solución, que agrega la funcionalidad de reducción y es aún más simple y rápido, supongo.

$("textarea").keyup(function(e) {
    $(this).height(30);
    $(this).height(this.scrollHeight + parseFloat($(this).css("borderTopWidth")) + parseFloat($(this).css("borderBottomWidth")));
});

Probado en el navegador actual Chrome, Firefox y Android 2.3.3.

Puede ver destellos de las barras de desplazamiento en algunos navegadores. Agregue este CSS para resolver eso.

textarea{ overflow:hidden; }
drolex
fuente
no funciona bien en absoluto: / cada carácter que escribo, agrega altura.
vsync
1
¡Funciona perfecto para mí! Definitivamente no hay nada en el código simple para hacer lo que usted dice que hace.
drolex
1
Sí, lo veo ahora, su código debe tener la línea que establece la altura a 30 inicialmente. esto es probablemente una ilne no-necesaria, ya que obliga al desarrollador para modificar el código, en lugar del código de entender y adaptarse al área de texto,
VSYNC
1
Eso es incorrecto El desarrollador no necesita modificar el código. Se requiere establecer la altura en 30 y funciona para todo. El usuario nunca ve que eso suceda. Así es como puede reducir el área de texto. El código comprende y se adapta al área de texto. Ese es el punto.
drolex
Estás en lo correcto. página de demostración: jsbin.com/ObEcoza/2/edit (establecer la altura en 1pxparece ser mejor)
vsync
10

Para definir un área de texto auto expandible, debe hacer dos cosas:

  1. Expanda una vez que haga clic en la tecla Intro, o escriba contenido en más de una línea.
  2. Y reduzca al desenfoque para obtener el tamaño real si el usuario ha ingresado espacios en blanco. ( Bonificación )

Aquí hay una función hecha a mano para realizar la tarea.

Funciona bien con casi todos los navegadores (<IE7) . Aquí está el método:

    //Here is an event to get TextArea expand when you press Enter Key in it.
    // intiate a keypress event
    $('textarea').keypress(function (e) {  
       if(e.which == 13)   {   
       var control = e.target;                     
       var controlHeight = $(control).height();          
      //add some height to existing height of control, I chose 17 as my line-height was 17 for the control    
    $(control).height(controlHeight+17);  
    }
    }); 

$('textarea').blur(function (e) {         
    var textLines = $(this).val().trim().split(/\r*\n/).length;      
    $(this).val($(this).val().trim()).height(textLines*17);
    });

AQUÍ hay una publicación sobre esto.

abierto y libre
fuente
6

He usado el complemento Textarea Expander jQuery antes con buenos resultados.

richsage
fuente
1
Un cuadro de texto (elemento de texto de entrada, supongo) no es multilínea. Use un área de texto, pero póngale un estilo apropiado: filas, columnas, etc., y luego use el complemento de crecimiento automático como se indicó anteriormente.
richsage
4

Todos deberían probar este complemento jQuery: xautoresize-jquery . Es realmente bueno y debería resolver tu problema.

danchoif2
fuente
Este me dio los mejores resultados y también es fácil de implementar.
bombardeo el
4
function autosize(textarea) {
    $(textarea).height(1); // temporarily shrink textarea so that scrollHeight returns content height when content does not fill textarea
    $(textarea).height($(textarea).prop("scrollHeight"));
}

$(document).ready(function () {
    $(document).on("input", "textarea", function() {
        autosize(this);
    });
    $("textarea").each(function () {
        autosize(this);
    });
});

(Esto no funcionará en Internet Explorer 9 o anterior, ya que hace uso del inputevento)

benrwb
fuente
en mi proyecto, ya que estoy representando cosas enteras en la página por Jquery y mecanografiado, su solución fue la única forma en que pude resolver mi problema gracias
Harry Sarshogh
3

Acabo de construir esta función para expandir áreas de texto en la carga de la página. Sólo cambia eacha keyupy ocurrirá cuando el área de texto se escribe en.

// On page-load, auto-expand textareas to be tall enough to contain initial content
$('textarea').each(function(){
    var pad = parseInt($(this).css('padding-top'));
    if ($.browser.mozilla) 
        $(this).height(1);
    var contentHeight = this.scrollHeight;
    if (!$.browser.mozilla) 
        contentHeight -= pad * 2;
    if (contentHeight > $(this).height()) 
        $(this).height(contentHeight);
});

Probado en Chrome, IE9 y Firefox. Desafortunadamente, Firefox tiene este error que devuelve el valor incorrecto para scrollHeight, por lo que el código anterior contiene una solución (hacky).

Simon East
fuente
3

Solucioné algunos errores en la respuesta proporcionada por Reigel (la respuesta aceptada):

  1. El orden en que se reemplazan las entidades html ahora no causa código inesperado en el elemento sombra. (El original reemplazó ">" por "& ampgt;", causando un cálculo incorrecto de la altura en algunos casos raros).
  2. Si el texto termina con una nueva línea, la sombra ahora obtiene un carácter adicional "#", en lugar de tener una altura adicional fija, como es el caso en el original.
  3. Cambiar el tamaño del área de texto después de la inicialización actualiza el ancho de la sombra.
  4. ajuste de palabra agregado: palabra de interrupción para sombra, por lo que se rompe igual que un área de texto (forzando interrupciones para palabras muy largas)

Hay algunos problemas pendientes con respecto a los espacios. No veo una solución para los espacios dobles, se muestran como espacios individuales en la sombra (representación html). Esto no puede solucionarse usando & nbsp ;, porque los espacios deberían romperse. Además, el área de texto rompe una línea después de un espacio, si no hay espacio para ese espacio, romperá la línea en un punto anterior. Las sugerencias son bienvenidas.

Código corregido:

(function ($) {
    $.fn.autogrow = function (options) {
        var $this, minHeight, lineHeight, shadow, update;
        this.filter('textarea').each(function () {
            $this = $(this);
            minHeight = $this.height();
            lineHeight = $this.css('lineHeight');
            $this.css('overflow','hidden');
            shadow = $('<div></div>').css({
                position: 'absolute',
                'word-wrap': 'break-word',
                top: -10000,
                left: -10000,
                width: $this.width(),
                fontSize: $this.css('fontSize'),
                fontFamily: $this.css('fontFamily'),
                lineHeight: $this.css('lineHeight'),
                resize: 'none'
            }).appendTo(document.body);
            update = function () {
                shadow.css('width', $(this).width());
                var val = this.value.replace(/&/g, '&amp;')
                                    .replace(/</g, '&lt;')
                                    .replace(/>/g, '&gt;')
                                    .replace(/\n/g, '<br/>')
                                    .replace(/\s/g,'&nbsp;');
                if (val.indexOf('<br/>', val.length - 5) !== -1) { val += '#'; }
                shadow.html(val);
                $(this).css('height', Math.max(shadow.height(), minHeight));
            };
            $this.change(update).keyup(update).keydown(update);
            update.apply(this);
        });
        return this;
    };
}(jQuery));
Carlo Roosen
fuente
3

Código de SpYk3HH con adición para reducir el tamaño.

function get_height(elt) {
    return elt.scrollHeight + parseFloat($(elt).css("borderTopWidth")) + parseFloat($(elt).css("borderBottomWidth"));
}

$("textarea").keyup(function(e) {
    var found = 0;
    while (!found) {
        $(this).height($(this).height() - 10);
        while($(this).outerHeight() < get_height(this)) {
            $(this).height($(this).height() + 1);
            found = 1;
        };
    }
});
DSblizzard
fuente
¿Viste mi respuesta antes que la tuya?
drolex
1
Su solución no me conviene, hubo algún error, no recuerdo cuál.
DSblizzard 01 de
2

Esto me funcionó mejor:

$('.resiText').on('keyup input', function() { 
$(this).css('height', 'auto').css('height', this.scrollHeight + (this.offsetHeight - this.clientHeight));
});
.resiText {
    box-sizing: border-box;
    resize: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<textarea class="resiText"></textarea>

Nori
fuente
2

La gente parece tener soluciones muy trabajadas ...

Así es como lo hago:

  $('textarea').keyup(function()
  {
    var 
    $this  = $(this),
    height = parseInt($this.css('line-height'),     10),
    padTop = parseInt($this.css('padding-top'),     10),
    padBot = parseInt($this.css('padding-bottom'),  10);

    $this.height(0);

    var 
    scroll = $this.prop('scrollHeight'),
    lines  = (scroll  - padTop - padBot) / height;

    $this.height(height * lines);
  });

Esto funcionará con líneas largas, así como con saltos de línea ... crece y se contrae ...

superhéroe
fuente
1

Escribí esta función jquery que parece funcionar.

Sin embargo, debe especificar min-height en css y, a menos que desee hacer algo de codificación, debe tener dos dígitos. es decir, 12px;

$.fn.expand_ta = function() {

var val = $(this).val();
val = val.replace(/</g, "&lt;");
val = val.replace(/>/g, "&gt;");
val += "___";

var ta_class = $(this).attr("class");
var ta_width = $(this).width();

var min_height = $(this).css("min-height").substr(0, 2);
min_height = parseInt(min_height);

$("#pixel_height").remove();
$("body").append('<pre class="'+ta_class+'" id="pixel_height" style="position: absolute; white-space: pre-wrap; visibility: hidden; word-wrap: break-word; width: '+ta_width+'px; height: auto;"></pre>');
$("#pixel_height").html(val);

var height = $("#pixel_height").height();
if (val.substr(-6) == "<br />"){
    height = height + min_height;
};
if (height >= min_height) $(this).css("height", height+"px");
else $(this).css("height", min_height+"px");
}
Davie Dave
fuente
1

Para cualquiera que use el complemento publicado por Reigel, tenga en cuenta que esto deshabilitará la funcionalidad de deshacer en Internet Explorer (vaya a probar la demostración).

Si esto es un problema para usted, sugeriría usar el complemento publicado por @richsage, ya que no sufre este problema. Para obtener más información, consulte el segundo punto en Búsqueda del área de texto de cambio de tamaño definitivo .

usuario1018494
fuente
1

Quería animaciones y auto encogimiento. La combinación es aparentemente difícil, porque a la gente se le ocurrieron soluciones bastante intensas. También lo hice a prueba de múltiples textos. Y no es tan ridículamente pesado como el complemento jQuery.

Me basé en la respuesta de vsync (y la mejora que hizo), http://codepen.io/anon/pen/vlIwj es el codepen para mi mejora.

HTML

<textarea class='autoExpand' rows='3' data-min-rows='3' placeholder='Auto-Expanding Textarea'></textarea>

CSS

body{ background:#728EB2; }

textarea{  
  display:block;
  box-sizing: padding-box;
  overflow:hidden;

  padding:10px;
  width:250px;
  font-size:14px;
  margin:50px auto;
  border-radius:8px;
  border:6px solid #556677;
  transition:all 1s;
  -webkit-transition:all 1s;
}

JS

var rowheight = 0;

$(document).on('input.textarea', '.autoExpand', function(){
    var minRows = this.getAttribute('data-min-rows')|0,
        rows    = this.value.split("\n").length;
    $this = $(this);
    var rowz = rows < minRows ? minRows : rows;
    var rowheight = $this.attr('data-rowheight');
    if(!rowheight){
      this.rows = rowz;
      $this.attr('data-rowheight', (this.clientHeight  - parseInt($this.css('padding-top')) - parseInt($this.css('padding-bottom')))/ rowz);
    }else{
      rowz++;
      this.style.cssText = 'height:' + rowz * rowheight + 'px'; 
    }
});
Lodewijk
fuente
Nota: he notado que a veces funciona mejor con box-sizing: content-box. Sin embargo, no estoy completamente seguro de por qué, debería procesar el relleno correctamente :(
Lodewijk
1

Hay muchas respuestas para esto, pero encontré algo muy simple, adjunte un evento keyup al área de texto y verifique la tecla enter, presione el código 13

keyPressHandler(e){ if(e.keyCode == 13){ e.target.rows = e.target.rows + 1; } }

Esto agregará otra fila a su área de texto y puede diseñar el ancho usando CSS.

Prostil Hardi
fuente
1

Digamos que estás tratando de lograr esto usando Knockout ... así es como:

En pagina:

<textarea data-bind="event: { keyup: $root.GrowTextArea }"></textarea>

En vista del modelo:

self.GrowTextArea = function (data, event) {
    $('#' + event.target.id).height(0).height(event.target.scrollHeight);
}

Esto debería funcionar incluso si tiene varias áreas de texto creadas por un foreach Knockout como yo.

Barry Franklin
fuente
1

Solución simple:

HTML:

<textarea class='expand'></textarea>

JS:

$('textarea.expand').on('input', function() {
  $(this).scrollTop($(this).height());
});
$('textarea.expand').scroll(function() {
  var h = $(this).scrollTop();
  if (h > 0)
    $(this).height($(this).height() + h);
});

https://fiddle.jshell.net/7wsnwbzg/

Pablo Werlang
fuente
1

La solución más simple:

html:

<textarea class="auto-expand"></textarea>

css:

.auto-expand {
    overflow:hidden;
    min-height: 80px;
}

js (jquery):

$(document).ready(function () {
 $("textarea.auto-expand").focus(function () {
        var $minHeight = $(this).css('min-height');
        $(this).on('input', function (e) {
            $(this).css('height', $minHeight);
            var $newHeight = $(this)[0].scrollHeight;
            $(this).css('height', $newHeight);
        });
    });       
});
Katya Dolgov
fuente
1

Solución con JS puro

function autoSize() {
  if (element) {
    element.setAttribute('rows', 2) // minimum rows
    const rowsRequired = parseInt(
      (element.scrollHeight - TEXTAREA_CONFIG.PADDING) / TEXTAREA_CONFIG.LINE_HEIGHT
    )
    if (rowsRequired !== parseInt(element.getAttribute('rows'))) {
      element.setAttribute('rows', rowsRequired)
    }
  }
}

https://jsfiddle.net/Samb102/cjqa2kf4/54/

samb102
fuente
1

Esta es la solución que terminé usando. Quería una solución en línea, y hasta ahora parece funcionar muy bien:

<textarea onkeyup="$(this).css('height', 'auto').css('height', this.scrollHeight + this.offsetHeight - this.clientHeight);"></textarea>
Trevor Meier
fuente
1

function autoResizeTextarea() {
  for (let index = 0; index < $('textarea').length; index++) {
    let element = $('textarea')[index];
    let offset = element.offsetHeight - element.clientHeight;
    $(element).css('resize', 'none');
    $(element).on('input', function() {
      $(this).height(0).height(this.scrollHeight - offset - parseInt($(this).css('padding-top')));
    });
  }
}

https://codepen.io/nanachi1/pen/rNNKrzQ

Esto debería funcionar.

nanachi1
fuente
0

@Georgiy Ivankin hizo una sugerencia en un comentario, la usé con éxito :) -, pero con ligeros cambios:

$('#note').on('keyup',function(e){
    var maxHeight = 200; 
    var f = document.getElementById('note'); 
    if (f.clientHeight < f.scrollHeight && f.scrollHeight < maxHeight ) 
        { f.style.height = f.scrollHeight + 'px'; }
    });      

Deja de expandirse después de alcanzar una altura máxima de 200 px

davidman77
fuente
0

Antigua pregunta pero podrías hacer algo como esto:

html:

<textarea class="text-area" rows="1"></textarea>

jquery:

var baseH; // base scroll height

$('body')
    .one('focus.textarea', '.text-area', function(e) {
        baseH = this.scrollHeight;
    })
    .on('input.textarea', '.text-area', function(e) {
        if(baseH < this.scrollHeight) {
            $(this).height(0).height(this.scrollHeight);
        }
        else {
            $(this).height(0).height(baseH);
        }
    });

De esta manera, el cambio de tamaño automático se aplicará a cualquier área de texto con la clase "área de texto". También se reduce cuando se elimina el texto.

jsfiddle:

https://jsfiddle.net/rotaercz/46rhcqyn/

rotaercz
fuente
0

Prueba esto:

  $('textarea[name="mytextarea"]').on('input', function(){
    $(this).height('auto').height($(this).prop('scrollHeight') + 'px');
  }).trigger('input');
tim
fuente
0

Solución simple de jQuery:

$("textarea").keyup(function() {
    var scrollHeight = $(this).prop('scrollHeight') - parseInt($(this).css("paddingTop")) - parseInt($(this).css("paddingBottom"));

    if (scrollHeight > $(this).height()) {
        $(this).height(scrollHeight + "px");
    }
});

HTML:

<textarea rows="2" style="padding: 20px; overflow: hidden; resize: none;"></textarea>

El desbordamiento debe estar oculto . Cambiar el tamaño es ninguno si no desea que sea redimensionable con el mouse.

elano7
fuente