Espandi automaticamente un'area di testo usando jQuery


128

Come posso espandere automaticamente un'area di testo usando jQuery?

Ho una casella di testo per spiegare l'agenda della riunione, quindi desidero espandere quella casella di testo quando il testo della mia agenda continua a crescere nell'area della casella di testo.


la textarea è autoespandibile.
Andrew Sullivan,


Ti preghiamo di considerare di cambiare la tua domanda e di rimuovere la parola "jQuery"
vsync il

Risposte:


113

Ho provato un sacco e questo è fantastico. Il link è morto. La versione più recente è disponibile qui . Vedi sotto per la vecchia versione.
Puoi provare tenendo premuto il tasto Invio in textarea. Confronta l'effetto con l'altro plugin textarea a espansione automatica ....

modifica in base al commento

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

nota: è necessario includere i file js necessari ...

Per evitare che la barra di scorrimento nella textarea da lampeggiante on & off durante l'espansione / contrazione, è possibile impostare il overflowper hiddencosì:

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




Aggiornare:

Il link sopra è rotto. Ma puoi ancora ottenere i file javascript qui .


se il mio ID casella di testo è txtMeetingAgenda, allora come posso implementare la proprietà Auto textArea in jquery
Piyush

qui l'evento è definito o no
Piyush

si tratta solo di textarea ma di textbox. questo plugin funziona anche con textbox?
Piyush,

1
questo plugin non funziona bene, prova a ridimensionare automaticamente, è molto meglio
julesbou,

Funziona bene solo in un modo quando textarea sta crescendo. Ma quando inizi a cancellare il testo, non si riduce automaticamente l'altezza.
ekashking

166

Se non vuoi un plugin c'è una soluzione molto semplice

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

Vedo che funziona in un jsFiddle Ho usato per rispondere a un'altra domanda textarea qui .

Per rispondere alla domanda di farlo al contrario o di ridurlo man mano che il testo viene rimosso: jsFiddle

E se vuoi un plugin

@Jason ne ha progettato uno qui


1
Ho dovuto rimuovere + parseFloat ($ (this) .css ("borderTopWidth")) + parseFloat ($ (this) .css ("borderBottomWidth")), altrimenti gira all'infinito con una textarea disegnata con bootstrap
blacelle

3
Versione jQuery-less:if (this.clientHeight < this.scrollHeight) { this.style.height = this.scrollHeight + 'px'; }
Georgii Ivankin,

3
@metakungfu Beh, invece di limitarti al downgrade, forse puoi aiutare a migliorare la risposta. Non ho modo di testare la merda di mele e Safari per Windows è stato sospeso molto tempo fa. Quindi non posso davvero fare nulla per determinare perché non funzionerebbe. Per quanto riguarda il codice, non c'è niente di sbagliato in questa soluzione. Sei sicuro che sia il codice a rompere e non a rompere i safari in jsfiddle? Safari è piuttosto esigente e il violino ha appena subito un importante aggiornamento. Mayeb puoi aprire dev con e fornire qualche dettaglio in più?
SpYk3HH,

1
necessita anche di textarea overflow-y impostato su nascosto per evitare lo scrolling lampeggiante
iulial

2
Se desidero rimuovere le righe aggiunte, la dimensione ingrandita della casella di testo rimane la stessa, è possibile che possa anche ridimensionare automaticamente?
Steven

33

Cresce / restringe textarea. Questa demo utilizza jQuery per l'associazione di eventi, ma non è in alcun modo indispensabile.
( nessun supporto IE - IE non risponde alla modifica degli attributi delle righe )

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 (aggiornato)

$(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;
    });

2
perché il codice deve attendere un po 'che la lettera digitata venga stampata all'interno dell'area di testo e quindi modificare le dimensioni
dell'area di testo

1
Vedo, la soluzione si interrompe quando il testo viene copiato (CTRL + V) da qualsiasi fonte. Mentre, se il testo viene digitato manualmente, questo è fantastico e molto fluido.
Satya Kalluri,

1
@vsync: come modificheresti per più aree di testo? Cioè hai textarea1 e textarea2 e vuoi consentire ad entrambi di crescere?
jmoreno,

1
Questa dovrebbe essere la risposta migliore! Ho postato una domanda sulla base di che, se qualcuno è interessato: stackoverflow.com/questions/29930300/...
gsamaras

1
@AllyMurray - Sono andato ora e l'ho aggiornato a 16 poiché sembra dare un risultato migliore. e sì, questa è l'altezza della linea prevista
vsync il


20

Puoi provare questo

$('#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>


se vuoi ottenere scrollHeight da $ (questo), puoi usare $ (questo) .prop ('scrollHeight'); invece;)
Samuel Vicent,

3
lampeggia ad ogni interruzione di riga
joe

11

Grazie a SpYk3HH, ho iniziato con la sua soluzione e l'ho trasformata in questa soluzione, che aggiunge la funzionalità di riduzione ed è ancora più semplice e veloce, presumo.

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

Testato negli attuali browser Chrome, Firefox e Android 2.3.3.

È possibile che vengano visualizzati dei flash delle barre di scorrimento in alcuni browser. Aggiungi questo CSS per risolverlo.

textarea{ overflow:hidden; }

non funziona affatto bene: / ogni carattere che scrivo, aggiunge altezza.
vsync,

1
Funziona perfettamente per me! Non c'è assolutamente nulla nel codice semplice per fare ciò che dici.
drolex,

1
sì, lo vedo ora, il tuo codice deve avere la linea che imposta inizialmente l'altezza su 30. questo è probabilmente un ilne non necessario perché forza lo sviluppatore a modificare il codice, invece che il codice comprenda e si adatti alla textarea,
vsync,

1
Non è corretto Lo sviluppatore non ha bisogno di modificare il codice. È necessario impostare l'altezza su 30 e funziona per tutto. L'utente non vede mai che ciò accada. È così che è in grado di ridurre l'area di testo. Il codice comprende e si adatta alla textarea. Questo è il punto.
drolex,

Hai ragione. pagina demo: jsbin.com/ObEcoza/2/edit (l'impostazione dell'altezza 1pxsembra migliore)
vsync

10

Per definire un'area di testo espandibile automaticamente, devi fare due cose:

  1. Espandilo dopo aver fatto clic sul tasto Invio al suo interno o digita il contenuto su più di una riga.
  2. E ridurlo a sfocatura per ottenere le dimensioni effettive se l'utente ha inserito spazi bianchi. ( Bonus )

Ecco una funzione fatta a mano per svolgere il compito.

Funziona bene con quasi tutti i browser (<IE7) . Ecco il metodo:

    //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);
    });

QUI è un post su questo.


6

Ho già usato il plugin jQuery di Textarea Expander con buoni risultati.


1
Una casella di testo (presumo elemento di testo di input) non è multilinea. Usa un'area di testo ma modellala in modo appropriato - righe, colonne, ecc., Quindi usa il plugin di crescita automatica come sopra.
richsage

4

Tutti dovrebbero provare questo plugin jQuery: xautoresize-jquery . È davvero buono e dovrebbe risolvere il tuo problema.


Questo mi ha dato i migliori risultati ed è anche facile da implementare.
blitzkid,

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);
    });
});

(Questo non funzionerà in Internet Explorer 9 o precedenti poiché utilizza l' inputevento)


nel mio progetto, mentre sto realizzando intere cose nella pagina di Jquery e dattiloscritto, la tua soluzione è stata l'unico modo per risolvere il mio problema grazie
Harry Sarshogh

3

Ho appena creato questa funzione per espandere textareas su pageload. Basta cambiare eachper keyupe si verifica quando la textarea viene digitato.

// 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);
});

Testato su Chrome, IE9 e Firefox. Purtroppo Firefox ha questo bug che restituisce il valore errato per scrollHeight, quindi il codice sopra contiene una soluzione (hacky) per esso.


3

Ho corretto alcuni bug nella risposta fornita da Reigel (la risposta accettata):

  1. L'ordine in cui vengono sostituite le entità html ora non causa codice imprevisto nell'elemento shadow. (L'originale ha sostituito ">" con "& ampgt;", causando un calcolo errato dell'altezza in alcuni rari casi).
  2. Se il testo termina con una nuova riga, l'ombra ora ottiene un carattere aggiuntivo "#", invece di avere un'altezza aggiunta fissa, come nel caso dell'originale.
  3. Il ridimensionamento dell'area di testo dopo l'inizializzazione aggiorna la larghezza dell'ombra.
  4. aggiunto a capo automatico: break-word per shadow, quindi si rompe come una textarea (forzando le pause per parole molto lunghe)

Ci sono alcuni problemi rimanenti riguardanti gli spazi. Non vedo una soluzione per i doppi spazi, sono visualizzati come singoli spazi nell'ombra (rendering html). Questo non può essere sostituito usando & nbsp ;, perché gli spazi dovrebbero rompersi. Inoltre, l'area di testo interrompe una linea dopo uno spazio, se non c'è spazio per quello spazio, interromperà la linea in un punto precedente. Suggerimenti sono ben accetti

Codice corretto:

(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));

3

Codice di SpYk3HH con aggiunta per ridurre le dimensioni.

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;
        };
    }
});

Hai visto la mia risposta prima della tua?
drolex,

1
La tua soluzione non mi soddisfa, c'è stato qualche errore, non ricordo quale.
DSblizzard

2

Questo ha funzionato meglio per me:

$('.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>


2

Le persone sembrano avere soluzioni molto lavorate ...

Ecco come lo faccio:

  $('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);
  });

Funzionerà con linee lunghe, così come con interruzioni di linea .. cresce e si restringe ..


1

Ho scritto questa funzione jquery che sembra funzionare.

Tuttavia, devi specificare l'altezza minima in CSS e, a meno che tu non voglia fare un po 'di codifica, deve avere una lunghezza di due cifre. cioè 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");
}



1

Volevo animazioni e restringimento automatico. La combinazione è apparentemente difficile, perché le persone hanno trovato soluzioni piuttosto intense per questo. L'ho reso anche multi-textarea-proof. E non è così ridicolmente pesante come il plugin jQuery.

Mi sono basato sulla risposta di vsync (e sul miglioramento che ha apportato per questo), http://codepen.io/anon/pen/vlIwj è il codice per il mio miglioramento.

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'; 
    }
});

Nota: ho notato che a volte funziona meglio con il dimensionamento dei box: content-box. Non sono del tutto sicuro del perché, tuttavia, dovrebbe elaborare correttamente il riempimento :(
Lodewijk,

1

Ci sono molte risposte per questo, ma ho trovato qualcosa di molto semplice, allego un evento di keyup alla textarea e controlla la chiave di invio premi il codice chiave è 13

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

Ciò aggiungerà un'altra riga alla tua area di testo e potrai modellare la larghezza usando CSS.


1

Supponiamo che tu stia cercando di ottenere questo risultato usando Knockout ... ecco come:

Nella pagina:

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

In vista modello:

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

Questo dovrebbe funzionare anche se hai più textareas create da un Knockout foreach come me.


1

Soluzione semplice:

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/


1

La soluzione più semplice:

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);
        });
    });       
});

1

Soluzione 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/


1

Questa è la soluzione che ho finito per usare. Volevo una soluzione in linea, e finora sembra funzionare alla grande:

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

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

questo dovrebbe funzionare.


0

@Georgiy Ivankin ha fatto un suggerimento in un commento, l'ho usato con successo :) -, ma con lievi modifiche:

$('#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'; }
    });      

Smette di espandersi dopo aver raggiunto un'altezza massima di 200 px


0

Vecchia domanda ma potresti fare qualcosa del genere:

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);
        }
    });

In questo modo il ridimensionamento automatico si applicherà a qualsiasi area di testo con la classe "area di testo". Si restringe anche quando il testo viene rimosso.

jsfiddle:

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


0

Prova questo:

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

0

Semplice soluzione 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>

L'overflow dovrebbe essere nascosto . Il ridimensionamento è nessuno se non si desidera renderlo ridimensionabile con il mouse.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.