Creazione di un'area di testo con ridimensionamento automatico


366

C'era un altro thread su questo , che ho provato. Ma c'è un problema: iltextarea non si riduce se si elimina il contenuto. Non riesco a trovare alcun modo per ridurlo alla dimensione corretta - il clientHeightvalore ritorna come dimensione intera di textarea, non il suo contenuto.

Il codice da quella pagina è sotto:

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 risposta accettata per il thread che hai collegato funziona per me. L'aggiunta di interruzioni di riga espande l'area di testo e rimuovendole riduce l'area di testo. Quale browser utilizzate?
EndangeredMassa

3
La mia funzione non funziona. È necessariamente digitare una nuova riga alla fine della riga. Questa è la soluzione migliore. james.padolsey.com/javascript/jquery-plugin-autoresize

Puoi provare il mio plugin per questo: github.com/AndrewDryga/jQuery.Textarea.Autoresize
Andrew Dryga


Ho creato un pacchetto per questo se stai usando reazioni
Martin Dawson il

Risposte:


230

Questo funziona per me (Firefox 3.6 / 4.0 e 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>

Se vuoi provarlo su jsfiddle Inizia con una sola riga e cresce solo la quantità esatta necessaria. Va bene per un singolo textarea, ma volevo scrivere qualcosa in cui avrei avuto molti molti molti textareas (circa quanto uno avrebbe normalmente linee in un grande documento di testo). In quel caso è molto lento. (In Firefox è follemente lento.) Quindi mi piacerebbe davvero un approccio che utilizza CSS puro. Questo sarebbe possibile con contenteditable, ma voglio che sia solo in chiaro.


13
Lo fa! Creato un jsfiddle per te: jsfiddle.net/CbqFv Ora funziona in Chrome, Firefox e IE8 - anche se è un po 'glitch in IE8. Man mano che aumenti o diminuisci il numero di linee, si spaventa un po '. Come potreste aver visto nel plugin di ridimensionamento automatico per jQuery, aggirano il problema clonando l'area di testo, impostando la sua altezza su auto anziché sull'originale, quindi usando quello per impostare l'altezza di scorrimento sull'originale. L'ho fatto in questo violino aggiornato: jsfiddle.net/CbqFv/2 Risolve il problema IE ma Firefox smette di funzionare.
Chris Moschini,

3
@HelenNeely: quindi non utilizzare un ID. Ad esempio, usa una classe e fai ciò che init fa per tutti gli elementi di quella classe. Questo dovrebbe essere un compito per principianti.
Panzi,

3
@ DenilsonSá Se si potesse solo supporre che vengano utilizzati solo browser moderni, il Web sarebbe un posto migliore.
Panzi,

2
Questo non funzionerà bene se una barra di scorrimento è coinvolta in IE11. Se usi questo violino jsfiddle.net/CbqFv e inserisci le linee fino a quando non hai una barra di scorrimento, lo vedrai. Qualche idea?
Kaljak,

6
Questo si interrompe completamente se l'area di testo si trova vicino alla fine della pagina inferiore - tutto a causa di style.height='auto'. Sospetto che la soluzione sia quella di aggiungere un fratello nascosto usato solo per la misurazione.
r-

372

UNA SOLUZIONE SEMPLICE ANCORA COMPLETA

Aggiornato il 2020-05-14 (Supporto browser migliorato per cellulari e tablet)

Il seguente codice funzionerà:

  • Inserimento chiave.
  • Con testo incollato (tasto destro e ctrl + v).
  • Con testo tagliato (tasto destro e ctrl + x).
  • Con testo precaricato.
  • Con tutto il sito di textarea (multiline textbox) .
  • Con Firefox (v31-67 testato).
  • Con Chrome (v37-74 testato).
  • Con IE (v9-v11 testato).
  • Con Bordo (testato v14-v18).
  • Con IOS Safari .
  • Con browser Android .
  • Con JavaScript modalità rigorosa .
  • È W3C validato.
  • Ed è snello ed efficiente.

OPZIONE 1 (Con jQuery)

Questa opzione richiede jQuery ed è stata testata e funziona con 1.7.2 - 3.3.1

Semplice (aggiungi questo codice jquery al tuo file di script principale e dimenticalo.)

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


OPZIONE 2 (JavaScript puro)

Semplice (aggiungi questo JavaScript al tuo file di script principale e dimenticalo.)

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


OPZIONE 3 (estensione jQuery)

Utile se si desidera applicare un ulteriore concatenamento alle aree di testo che si desidera ridimensionare automaticamente.

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

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


AGGIORNAMENTO DI TEXTAREA VIA JAVASCRIPT

Quando si inietta contenuto in un'area di testo tramite JavaScript, aggiungere il seguente codice per richiamare la funzione nell'opzione 1.

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

ALTEZZA DI TEXTAREA PRESET

Per correggere l'altezza iniziale dell'area di testo dovrai aggiungere una condizione aggiuntiva:

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
Questa è un'ottima soluzione, sarebbe leggermente più comprensibile se il nome del metodo e il nome del parametro fossero aggiornati per essere veri nomi anziché singole lettere.
Chris Marisic,

5
@Obsidian Grazie! Ho appena capito perché ricevo sempre uno 0 —— Metto la textarea in un Bootstrap modale! Poiché inizialmente il modale è nascosto, textarea in esso avrà uno scrollHeight 😂😂
WTIFS

7
@Obsidian Fantastic !! (Opzione 3). Questa this.style.height = 'auto';è la correzione del comportamento magico. Ero così frustrato perché la scrollHeight aveva un comportamento così strano. L'altezza su auto, quindi abbinando scrollHeight nello stesso ciclo di rendering, mi fa ancora impazzire su come 'risolve' questo problema, anche se dovrebbe tecnicamente dipingere solo la seconda altezza.
Bit-less

2
Ho provato l'opzione 3 in Chrome oggi e ho dovuto fare un paio di modifiche. 1) Non ridimensionerà sempre correttamente se hai una transizione "altezza" o "tutto" nell'area di testo. Consiglio di non utilizzare le transizioni che influiscono sull'altezza. 2) scrollHeight restituiva un minimo di due righe di altezza (forse perché è l'impostazione predefinita per textareas in Chrome) ma se cambi this.style.height = 'auto'; to this.style.height = '0px'; e aggiungi un'altezza minima per evitare che lo stato iniziale vada effettivamente a 0, scrollHeight restituirà correttamente una riga di altezza quando appropriato.
ZorroDeLaArena,

3
@Obsidian Puoi spiegare come this.style.height = 'auto';risolve il comportamento di scrollHeight? È solo magia.
Sidney,

63

La soluzione jQuery regola i CSS in base alle proprie esigenze

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 per jQuery 1.7 + ...

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

Ho creato un violino con lo stile minimo assoluto come punto di partenza per i tuoi esperimenti ... http://jsfiddle.net/53eAy/951/


5
Questo va bene, ma aggiungerei overflow-y: hidden;al CSS per evitare che la barra di scorrimento lampeggi brevemente quando si verifica il ridimensionamento.
brettjonesdev,

Non del tutto sicuro, ma senza di essa l'area di testo cresce di troppo. Penso che abbia a che fare con il modo in cui vengono calcolati gli elementi scrollHeight.
chim

1
Usa più eventi per far funzionare l'ampia verità dello scenario $('textarea.auto-resize').on('change cut paste drop keyup', function(){...})
raxith,

1
Salta come un matto in Chrome 40 Vinci 8.1 su testi più lunghi del viewport. Lo rende abbastanza inutilizzabile.
Tobibeer,

1
Tenendo premuto enter (newline) si ottiene lo scorrimento. La dimensione non si regola fino a quando il tasto non viene rilasciato.
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>

Testato in Firefox 14 e Chromium 18. I numeri 24 e 12 sono arbitrari, prova per vedere cosa ti si addice meglio.

Potresti fare a meno dei tag di stile e di script, ma diventa un imho un po 'disordinato (questo è HTML + JS vecchio stile e non è incoraggiato).

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

Modifica: codice modernizzato. Attributo onkeyup modificato in addEventListener.
Modifica: keydown funziona meglio di keyup
Edit: dichiara la funzione prima di usare
Edit: input funziona meglio di keydown (thnx @ WASD42 & @ MA-Maddin)

jsfiddle


3
Questo ha alcuni svantaggi: 1) Textarea non verrebbe ridimensionato, quindi l'utente incolla qualcosa solo con i suoi pulsanti del mouse; 2) Se l'utente incollerà qualcosa usando la tastiera (Ctrl + V) l'area di testo verrà ridimensionata solo quando rilascerà Ctrl. Se l'utente premerà Ctrl + V più volte, l'area di testo crescerà solo dopo l'ultima. Dovresti aggiungere la stessa funzione per incollare, tagliare, modificare e rilasciare anche eventi.
WASD42,

Quindi usa semplicemente l' inputevento. Vedi stackoverflow.com/a/14029861/1951524
Martin Schneider il

Versione migliorata con textareasupporto multiplo come one-liner:document.querySelectorAll('textarea').forEach(function(te){ te.addEventListener("input", function() { this.style.height='24px'; this.style.height=this.scrollHeight+12+'px'; }); });
Meisner

1
@Meisner È più corto, ma non direi che è "migliorato". Con una funzione anonima, non è possibile chiamare removeEventListenere ripulire i listener di eventi. Ciò è particolarmente importante quando si creano listener di eventi ovunque in un ciclo forEach. Inoltre, a mio avviso, la leggibilità è molto più importante della concisione.
GijsjanB

per gli altri e per il futuro, assicurati che la box-sizing: border-box;proprietà sia impostata altrimenti la textarea espande di 4px per ogni evento onInput. Ho trascorso circa 3 ore fino a quando ho capito che questo era il problema.
AIon,

24

La soluzione migliore (funziona ed è breve) per me è:

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

Funziona come un incantesimo senza battere ciglio con la pasta (anche con il mouse), tagliare, entrare e si restringe alla giusta dimensione.

Dai un'occhiata a jsFiddle .


Eccezionale!!! un affare di linea! domanda sciocca ho posso aggiungere un'animazione quando si ridimensiona? come se la casella di testo si ridimensionasse delicatamente piuttosto che passare alla dimensione?
user2513846

1
@ user2513846 Sembra che non sia possibile progettare l'editing su più righe. Ho fatto un esempio di animare la dimensione della textarea: jsfiddle.net/yk2g333e Come sapete, il cursore del testo scende verso e di linea o punto, quindi se non c'è pausa in questo momento non c'è nulla da animare. Ma mettere in pausa sarà fastidioso per l'utente.
vatavale,

1
@ user2513846 Tuttavia, con un'altra riga vuota alla fine di textarea, è possibile avere un'animazione fluida: jsfiddle.net/p23erdfr
vatavale

16

Stai utilizzando il valore più alto dell'attuale clientHeight e del contenuto scrollHeight. Quando si riduce lo scrollHeight rimuovendo il contenuto, l'area calcolata non può ridursi perché clientHeight, precedentemente impostato da style.height, lo tiene aperto. Potresti invece prendere un max () di scrollHeight e un valore di altezza minima che hai predefinito o calcolato da textarea.rows.

In generale, probabilmente non dovresti davvero fare affidamento su scrollHeight sui controlli del modulo. A parte il fatto che scrollHeight è tradizionalmente meno ampiamente supportato rispetto ad alcune delle altre estensioni di IE, HTML / CSS non dice nulla su come i controlli dei moduli sono implementati internamente e non sei garantito che scrollHeight sarà qualcosa di significativo. (Tradizionalmente alcuni browser hanno utilizzato i widget del sistema operativo per l'attività, rendendo impossibile l'interazione CSS e DOM sul proprio interno.) Almeno annusare l'esistenza di scrollHeight / clientHeight prima di provare ad abilitare l'effetto.

Un altro possibile approccio alternativo per evitare il problema se è importante che funzioni in modo più ampio potrebbe essere quello di utilizzare un div nascosto dimensionato alla stessa larghezza dell'area di testo e impostato nello stesso carattere. Al keyup, copi il testo dall'area di testo in un nodo di testo in div nascosto (ricordando di sostituire '\ n' con un'interruzione di riga e di scappare correttamente '<' / '&' se stai usando innerHTML). Quindi semplicemente misurando l'offset del divHeight ti darà l'altezza di cui hai bisogno.


1
Con quali browser dovrebbero avere problemi con scrollHeighttextareas? Funziona bene con le attuali versioni di IE, Firefox e Opera ...
Christoph,

1
L'unico che devo tenere è Konqueror, che restituisce clientHeight come scrollHeight. Questo è un comportamento che ci si può aspettare a meno che il browser non applichi il modello di casella CSS all'interno dei widget, cosa che non hanno sempre fatto e che lo standard non dice di dover fare.
Bobince,

14

Se non hai bisogno di supportare IE8 puoi usare l' 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));
}

Ora devi solo aggiungere alcuni CSS e hai finito:

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

Uso:

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

Puoi leggere di più su come funziona sul mio post sul blog .


1
Bella soluzione, ma necessita di una piccola correzione. Quando viene caricato il contenuto di textarea f.ex. dal database, textarea rimane piccola. È necessario attivare l' inputevento durante l'inizializzazione nel ciclo foreach.
Ajax,

11

dimensione dell'auto

https://github.com/jackmoore/autosize

Funziona da solo, autonomo, è popolare (3.0k + GitHub stelle a partire da ottobre 2018), disponibile su cdnjs ) e leggero (~ 3.5k). demo:

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

A proposito, se si utilizza l'editor ACE, utilizzare maxLines: Infinity: Regola automaticamente l'altezza in base ai contenuti nell'editor Ace Cloud 9


2
La versione 2 è stata rilasciata nel febbraio 2015. È diventata più semplice e non dipende più da jQuery
croccante

Mi dispiace, funziona. Forse ero in un altro browser .. quindi, penso che sia meglio se ignori il mio commento ..
Toni Michel Caubet,

@ToniMichelCaubet ah, OK forse problema CDN allora. Fammi controllare.
Ciro Santilli 2 冠状 病 六四 事件 法轮功

Il autosizeplug-in non consente di ridimensionare manualmente utilizzando l'icona di ridimensionamento in textarea.
j4v1,

7

Ho trovato una fodera da qui ;

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

6

Qualcuno ha considerato contenteditable? Non scherzare con lo scorrimento, e l'unico JS che mi piace a riguardo è se hai intenzione di salvare i dati su sfocatura ... e apparentemente, è compatibile su tutti i browser più diffusi: http://caniuse.com/#feat = contenteditable

Modificalo in modo che appaia come una casella di testo e si ridimensiona automaticamente ... Trasforma la sua altezza minima in altezza del testo preferita.

La cosa interessante di questo approccio è che puoi salvare e taggare su alcuni browser.

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 aggiungerà gli elementi <div> su INVIO.
sbaechler

contenteditableè buono, ma se vuoi il testo in chiaro ha bisogno di un sacco di opzioni come -webkit-user-modify: read-write-plaintext-onlye white-space: pre-wrap.
mik01aj,

@_sbaechler: i <div> s sono omessi durante l'utilizzo [dom-element].innerText. @WebmasterG IMHO sarebbe bello omettere jquery (per trasparenza) e includere l'esempio in questa pagina tramite frammento di codice eseguibile anziché su jsfiddle.
Adabru,

4

Ho usato il seguente codice per più textareas. Funziona bene in Chrome 12, Firefox 5 e IE 9, anche con le azioni di eliminazione, taglia e incolla eseguite nelle aree di testo.

<!-- 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

C'è un approccio leggermente diverso.

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

L'idea è di copiare il testo da textareadentro pree lasciare che CSS si assicuri che abbiano le stesse dimensioni.

Il vantaggio è che i framework presentano strumenti semplici per spostare il testo senza toccare alcun evento. Vale a dire, in AngularJS aggiungeresti ng-model="foo" ng-trim="false"a textareae ng-bind="foo + '\n'"a pre. Vedi un violino .

Assicurati solo che preabbia la stessa dimensione del carattere textarea.


1
" Assicurati solo che preabbia la stessa dimensione del carattere deltextarea " - Hanno bisogno della stessa line-heighte uguale quantità di paddinge / o borderanche. Questa è la migliore soluzione per Angular.
Jamie Barker,

4

Quanto segue funziona per tagliare, incollare, ecc., Indipendentemente dal fatto che tali azioni provengano dal mouse, una scorciatoia da tastiera, selezionando un'opzione da una barra dei menu ... diverse risposte adottano un approccio simile ma non tengono conto della casella- dimensionamento, motivo per cui applicano erroneamente lo stile overflow: hidden .

Faccio quanto segue, che funziona anche bene con max-heighte rowsper altezza minima e massima.

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>

Per completezza assoluta, è necessario chiamare la adjustfunzione in alcune altre circostanze:

  1. Eventi di ridimensionamento della finestra, se la larghezza di textarea modifiche cambia con il ridimensionamento della finestra o altri eventi che modificano la larghezza dell'area di testo
  2. Quando il textarea's displaymodifiche degli attributi di stile, per esempio quando si passa da none(nascosto) perblock
  3. Quando il valore di textareaviene modificato a livello di codice

Nota che usare window.getComputedStyleo ottenere currentStylepuò essere un po 'costoso dal punto di vista computazionale, quindi potresti voler memorizzare il risultato nella cache.

Funziona con IE6, quindi spero davvero che sia abbastanza buono supporto.


4

Come approccio diverso, è possibile utilizzare un <span>che regola automaticamente le sue dimensioni. Dovrai renderlo modificabile aggiungendo la contenteditable="true"proprietà e il gioco è fatto:

div {
  width: 200px;
}

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

L'unico problema di questo approccio è che se desideri inviare il valore come parte del modulo, dovrai farlo da solo in JavaScript. Farlo è relativamente facile. Ad esempio, è possibile aggiungere un campo nascosto e, in onsubmitcaso di modulo, assegnare il valore di spanal campo nascosto che verrà quindi automaticamente inviato con il modulo.


C'è già una risposta utilizzando contenteditable in questa pagina: stackoverflow.com/questions/454202/...
adabru

@adabru Sì, ma le due risposte non sono uguali. La Toyota produce macchine rosse e anche la Ford macchine rosse, ma sono diverse, no? Se ti piace di più l'altra risposta, allora seguila. Ma ci sono quelli che apprezzano di più la mia risposta e la seguono. Avere diverse opzioni è buono.
Racil Hilan,

3

Alcune correzioni. Funziona perfettamente in 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;
  });

funziona finché le linee non traboccano, quindi non si adattano.
Tomáš Kafka,

funziona subito, ottimo (firefox 72)
Mikeys4u,

2

Conosco un modo breve e corretto di implementarlo con jquery. Non sono necessari div nascosti extra e funziona nella maggior parte dei browser

<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 .live()è stato deprecato. api.jquery.com/live In genere ti consigliamo di utilizzare .on()invece.
Luca,

2

Non so se qualcuno menziona in questo modo, ma in alcuni casi è possibile ridimensionare l'altezza con l'attributo di righe

textarea.setAttribute('rows',breaks);

dimostrazione


1
Funziona solo se hai white-space: nowrap;. Quando una riga si sposta su un'altra riga senza interruzione di riga, l'area di testo non verrà più regolata correttamente.
Yeti,

2

Ecco una direttiva angularjs per la risposta di 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>

Dovresti piuttosto usare $ timeout che setTimout - questo farà in modo che il modello venga inizializzato (non è necessario specificare i millisecondi - verrà eseguito dopo il ciclo di digest angolare). Anche element = element [0]; è una pessima pratica ... Ad ogni modo, la soluzione non è buona per me poiché ho bisogno che textarea sia a una riga fino a quando non ci sarà più testo.
Karol Websky,

2

È possibile utilizzare JQuery per espandere textareadurante la digitazione:

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


Soluzione più pulita. ma come dovremmo smettere di usare jQuery: textarea.addEventListener ('keyup', () => {textarea.style.height = 0; textarea.style.height = ${textarea.scrollHeight}px;});
Toni Michel Caubet,

2

Coloro che vogliono ottenere lo stesso nelle nuove versioni di Angular.

Prendi 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>

Sto anche aggiungendo un altro caso d'uso che può rivelarsi utile per alcuni utenti che leggono il thread, quando l'utente desidera aumentare l'altezza dell'area di testo a una certa altezza e quindi utilizzarla overflow:scroll, il metodo sopra può essere esteso per ottenere il caso d'uso menzionato.

  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

Alcune delle risposte qui non tengono conto dell'imbottitura.

Supponendo che tu abbia un massimo, non vuoi andare oltre, questo ha funzionato per me:

    // 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 approccio ancora più semplice e più pulito è questo:

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

// e il 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
}

Tutto ciò che serve è aggiungere la .auto-heightclasse a qualsiasi textareadestinazione.

Testato in FF, Chrome e Safari. Fammi sapere se questo non funziona per te, per qualsiasi motivo. Ma questo è il modo più semplice e pulito in cui ho trovato che funzionasse. E funziona benissimo! : D


Hai provato a rimuovere il testo dopo la modifica? La textarea è crollata?
18C

1

Questo codice funziona per incollare e selezionare anche elimina.

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>

Ecco il JSFiddle


1

Raccomando la libreria javascript da http://javierjulio.github.io/textarea-autosize .

Per commenti, aggiungi esempio codeblock sull'utilizzo del plug-in:

<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 minimo richiesto:

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

1

MakeTextAreaResisable che utilizza 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

la mia implementazione è molto semplice, conta il numero di righe nell'input (e almeno 2 righe per mostrare che è una textarea):

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

esempio di lavoro completo con stimolo: https://jsbin.com/kajosolini/1/edit?html,js,output

(e questo funziona ad esempio con l'handle di ridimensionamento manuale del browser)


2
Funziona solo se interrompi la linea premendo "invio". Se il testo è più lungo della larghezza della textarea ma non si preme "invio", non si espande.
Nathalia Xavier,

1

La risposta accettata funziona bene. Ma questo è un sacco di codice per questa semplice funzionalità. Il codice qui sotto farà il trucco.

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

0

Ecco cosa ho fatto durante l'utilizzo di Helper HTML MVC per TextArea. Ho avuto alcuni elementi textarea, quindi ho dovuto distinguerli usando l'ID modello.

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

e nello script ha aggiunto questo:

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

L'ho testato su IE10 e Firefox23


0

Puoi usare questo codice:

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