Criando uma área de texto com redimensionamento automático

366

Havia outra discussão sobre isso , que eu tentei. Mas há um problema: o textareanão encolhe se você excluir o conteúdo. Não consigo encontrar nenhuma maneira de reduzi-lo ao tamanho correto - o clientHeightvalor volta como o tamanho total dotextarea , e não o seu conteúdo.

O código dessa página está abaixo:

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 )
    };
}
DisgruntledGoat
fonte
A resposta aceita para o segmento que você vinculou funciona para mim. Adicionar quebras de linha expande a área de texto e remove-as e reduz a área de texto. Qual navegador você está usando?
EndangeredMassa
3
Minha função comete erros. É necessariamente digitar nova linha no final da linha. Esta é a melhor solução. james.padolsey.com/javascript/jquery-plugin-autoresize
Você pode tentar o meu plugin para isso: github.com/AndrewDryga/jQuery.Textarea.Autoresize
Andrew Dryga
possível duplicata do Autosizing textarea usando o protótipo
Ciro Santilli
Eu criei um pacote para este se você estiver usando reagir: npmjs.com/package/react-fluid-textarea
Martin Dawson

Respostas:

230

Isso funciona para mim (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 você quiser experimentá-lo no jsfiddle Começa com uma única linha e cresce apenas a quantidade exata necessária. Não há problema em um single textarea, mas eu queria escrever algo em que tivesse muitos e muitos textarea(aproximadamente o que normalmente teria linhas em um documento de texto grande). Nesse caso, é realmente lento. (No Firefox, é incrivelmente lento.) Então, eu realmente gostaria de uma abordagem que use CSS puro. Isso seria possível com contenteditable, mas eu quero que seja apenas texto sem formatação.

panzi
fonte
13
Faz! Criou um jsfiddle para você: jsfiddle.net/CbqFv Ele agora funciona no Chrome, Firefox e IE8 - embora seja um pouco problemático no IE8. À medida que você aumenta ou diminui o número de linhas, fica um pouco assustador. Como você pode ter visto no plug-in de redimensionamento automático do jQuery, eles resolvem isso clonando a área de texto, definindo sua altura como automática em vez do original e usando-o para definir a altura da rolagem no original. Eu fiz isso neste violino atualizado: jsfiddle.net/CbqFv/2 Ele resolve o problema do IE, mas o Firefox para de funcionar.
Chris Moschini
3
@HelenNeely: Então não use um ID. Por exemplo, use uma classe e faça o que o init faz para todos os elementos dessa classe. Essa deve ser uma tarefa para iniciantes.
panzi
3
@ DenilsonSá Se alguém pudesse supor que apenas navegadores modernos são usados, a Web seria um lugar melhor.
panzi
2
Isso não funcionará bem se uma barra de rolagem estiver envolvida no IE11. Se você usar esse violino jsfiddle.net/CbqFv e digitar linhas até obter uma barra de rolagem, você a verá. Alguma ideia?
kaljak
6
Isso é interrompido completamente se a área de texto estiver próxima ao final da página inferior - tudo volta e recua devido a isso style.height='auto'. Eu suspeito que a solução é adicionar um irmão oculto usado apenas para medição.
precisa
372

UMA SOLUÇÃO COMPLETA AINDA SIMPLES

Atualizado 2020-05-14 (Suporte aprimorado ao navegador para celulares e tablets)

O código a seguir funcionará:

  • Na entrada da tecla.
  • Com texto colado (clique com o botão direito do mouse e ctrl + v).
  • Com texto recortado (clique com o botão direito do mouse e ctrl + x).
  • Com texto pré-carregado.
  • Com todas as áreas de texto (caixas de texto com várias linhas ) site área de amplo.
  • Com o Firefox (v31-67 testado).
  • Com o Chrome (v37-74 testado).
  • Com o IE (v9-v11 testado).
  • Com o Edge (v14-v18 testado).
  • Com o IOS Safari .
  • Com o navegador Android .
  • Com o modo estrito de JavaScript .
  • O w3c é validado.
  • E é simplificado e eficiente.

OPÇÃO 1 (com jQuery)

Esta opção requer jQuery e foi testada e está funcionando com 1.7.2 - 3.3.1

Simples (adicione esse código jquery ao seu arquivo de script mestre e esqueça-o.)

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


OPÇÃO 2 (JavaScript puro)

Simples (adicione este JavaScript ao seu arquivo de script mestre e esqueça-o.)

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


OPÇÃO 3 (extensão jQuery)

Útil se você deseja aplicar um encadeamento adicional às áreas de texto que deseja dimensionar 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);
      });
    });
  }
});

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


ATUALIZAÇÃO DA TEXTAREA ATRAVÉS DO JAVASCRIPT

Ao injetar conteúdo em uma área de texto via JavaScript, acrescente o código a seguir para chamar a função na opção 1.

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

ALTURA DE TEXTAREA PRESET

Para corrigir a altura inicial da área de texto, você precisará adicionar uma condição 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>

DreamTeK
fonte
12
Essa é uma ótima solução, seria um pouco mais compreensível se o nome do método e o nome do parâmetro fossem atualizados para serem nomes verdadeiros, em vez de letras individuais.
Chris Marisic # 3/14
5
@Obsidian Thanks! Acabei de descobrir por que sempre recebo um 0 - coloquei a área de texto em um modal Bootstrap! Como o modal está oculto no início, a área de texto terá um 0 scrollHeight 😂😂
WTIFS
7
@Obsidian Fantastic !! (Opção 3) A this.style.height = 'auto';é a correção do comportamento mágico. Fiquei tão frustrado por que o scrollHeight era tão estranho no comportamento. A altura para auto e, em seguida, igualando o scrollHeight no mesmo ciclo de renderização ainda me impressiona como ele 'corrige' esse problema, embora só deva pintar tecnicamente a segunda altura.
bit
2
Eu tentei a opção 3 no Chrome hoje e tive que fazer alguns ajustes. 1) Nem sempre será redimensionado corretamente se você tiver uma transição "altura" ou "tudo" na área de texto. Eu recomendo não usar transições que afetam a altura. 2) O scrollHeight estava retornando um mínimo de duas linhas de altura (talvez porque esse seja o padrão para as áreas de texto no Chrome), mas se você alterar this.style.height = 'auto'; para this.style.height = '0px'; e adicione uma altura mínima para impedir que o estado inicial realmente vá para 0, scrollHeight retornará corretamente uma linha de altura quando apropriado.
ZorroDeLaArena
3
@Obsidian Você pode explicar como this.style.height = 'auto';corrige o comportamento do scrollHeight? É apenas mágica.
Sidney
63

A solução jQuery ajusta o css para atender às suas necessidades

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

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

Eu criei um violino com o estilo mínimo absoluto como ponto de partida para suas experiências ... http://jsfiddle.net/53eAy/951/

chim
fonte
5
Isso é bom, mas eu acrescentaria overflow-y: hidden;ao css para impedir que a barra de rolagem pisque brevemente quando o redimensionamento ocorrer.
Brettjonesdev
Não tenho muita certeza, mas sem ela a área de texto cresce demais. Eu acho que tem a ver com a maneira que os elementos scrollHeight são calculados.
chim
11
Use vários eventos para tornar o trabalho de verdade gama de cenário $('textarea.auto-resize').on('change cut paste drop keyup', function(){...})
raxith
11
Salta como um louco no Chrome 40 Win 8.1 em textos mais longos que a janela de visualização. Torna inutilizável.
11132 Tobibeer
11
Manter pressionado enter (nova linha) resulta em rolagem. O tamanho não se ajusta até que a tecla seja liberada.
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>

Testado no Firefox 14 e Chromium 18. Os números 24 e 12 são arbitrários, teste para ver o que melhor combina com você.

Você pode ficar sem as tags de estilo e script, mas fica um pouco confuso (isso é HTML + JS no estilo antigo e não é recomendado).

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

Edit: código modernizado. Atributo onkeyup alterado para addEventListener.
Edit: keydown funciona melhor que keyup
Edit: declare a função antes de usar
Edit: input funciona melhor que keydown (thnx @ WASD42 e @ MA-Maddin)

jsfiddle

GijsjanB
fonte
3
Este tem alguns inconvenientes: 1) Textarea não seria redimensionado, então o usuário cola algo apenas com os botões do mouse; 2) Se o usuário colar algo usando o teclado (Ctrl + V), a área de texto será redimensionada somente quando ele soltar Ctrl. Se o usuário pressionar Ctrl + V várias vezes, a área de texto aumentará somente após a última. Você deve adicionar a mesma função para colar, cortar, alterar e soltar eventos também.
WASD42
Então, basta usar o inputevento. Veja stackoverflow.com/a/14029861/1951524
Martin Schneider
Versão melhorada com textareasuporte múltiplo como one-liner:document.querySelectorAll('textarea').forEach(function(te){ te.addEventListener("input", function() { this.style.height='24px'; this.style.height=this.scrollHeight+12+'px'; }); });
Meisner 29/01
11
@ Meisner É mais curto, mas eu não diria que é "melhorado". Com uma função anônima, não há como chamar removeEventListenere limpar seus ouvintes de eventos. Isso é especialmente importante ao criar ouvintes de eventos em todo o lugar em um loop forEach. Além disso, na minha opinião, a legibilidade é muito mais importante do que concisão.
GijsjanB
para outras pessoas e para o futuro, verifique se a box-sizing: border-box;propriedade está definida ou a área de texto explora em 4px para cada evento onInput. Passei três horas até descobrir que esse era o problema.
12/02/19
24

A melhor solução (funciona e é curta) para mim é:

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

Funciona como um encanto, sem piscar com pasta (com o mouse também), corte, entra e diminui para o tamanho certo.

Por favor, dê uma olhada no jsFiddle .

vatavale
fonte
Formidável!!! negócio de uma linha! pergunta boba ho Posso adicionar uma animação quando ela é redimensionada? como a caixa de texto meio que redimensionando suavemente em vez do salto para o tamanho?
user2513846
11
@ user2513846 Parece que não é possível pelo design da edição em várias linhas. Fiz um exemplo de animação do tamanho da área de texto: texto jsfiddle.net/yk2g333e Como você sabe, o cursor do texto desce na linha e no cursor ou acento circunflexo; portanto, se não houver pausa no momento, não haverá nada para animar. Mas pausar será muito chato para o usuário.
vatavale
11
@ user2513846 No entanto, com mais uma linha vazia no final da área de texto, é possível ter uma animação suave: jsfiddle.net/p23erdfr
vatavale
16

Você está usando o valor mais alto do clientHeight atual e do conteúdo scrollHeight. Quando você torna o scrollHeight menor removendo o conteúdo, a área calculada não pode ficar menor porque o clientHeight, definido anteriormente por style.height, o mantém aberto. Em vez disso, você pode usar um máximo () de scrollHeight e um valor mínimo de altura predefinido ou calculado a partir de textarea.rows.

Em geral, você provavelmente não deve confiar no scrollHeight nos controles de formulário. Além de o scrollHeight ser tradicionalmente menos amplamente suportado do que algumas das outras extensões do IE, o HTML / CSS não diz nada sobre como os controles de formulário são implementados internamente e você não tem garantia de que o scrollHeight será significativo. (Tradicionalmente, alguns navegadores usavam widgets de SO para a tarefa, impossibilitando a interação CSS e DOM em seus internos.) Pelo menos, fareje a existência de scrollHeight / clientHeight antes de tentar ativar o efeito.

Outra abordagem alternativa possível para evitar o problema, se é importante que ele funcione mais amplamente, pode ser o uso de uma div oculta, dimensionada para a mesma largura que a área de texto, e definida na mesma fonte. Ao digitar, você copia o texto da área de texto para um nó de texto na div oculta (lembre-se de substituir '\ n' por uma quebra de linha e escape '<' / '&' corretamente se estiver usando o innerHTML). Em seguida, basta medir o offsetHeight da div para obter a altura necessária.

bobince
fonte
11
Quais navegadores devem ter problemas nas áreas scrollHeightde texto? Funciona bem com as versões atuais do IE, Firefox e Opera ... #
Christoph
11
O único que tenho em mãos é o Konqueror, que retorna o clientHeight como scrollHeight. Esse é um comportamento que você pode esperar, a menos que o navegador aplique o modelo de caixa CSS nas partes internas dos widgets, algo que eles nem sempre fizeram e o padrão não diz que precisa.
21920
14

Se você não precisa oferecer suporte ao IE8, pode usar o 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));
}

Agora você só precisa adicionar um pouco de CSS e pronto:

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

Uso:

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

Você pode ler mais sobre como isso funciona no meu blog .

Maximilian Hoffmann
fonte
11
Solução agradável, mas precisa de pouca correção. Quando o conteúdo da área de texto é carregado, por exemplo, do banco de dados, a área de texto permanece pequena. Você deve disparar um inputevento durante a inicialização no ciclo foreach.
Ajax
11

tamanho automático

https://github.com/jackmoore/autosize

O Just works, autônomo, é popular (estrelas do GitHub a partir de outubro de 2018), disponível em 3.0k +, disponível no cdnjs ) e leve (~ 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>

BTW, se você estiver usando o editor ACE, use maxLines: Infinity: Ajustar automaticamente a altura ao conteúdo no editor Ace Cloud 9

Ciro Santilli adicionou uma nova foto
fonte
2
A versão 2 foi lançado em fevereiro de 2015. Tornou-se mais simples e não depende do jQuery mais
crocante
Desculpe, isso funciona. Talvez eu estivesse em outro navegador .. então, eu acho que é melhor se você ignorar o meu comentário ..
Toni Michel Caubet
@ToniMichelCaubet ah, OK, talvez problema na CDN então. Deixe-me ver.
Ciro Santilli publicou
O autosizeplug-in não permite redimensionar manualmente usando o ícone de redimensionamento na área de texto.
j4v1
7

Encontrei um forro daqui ;

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

Alguém já considerou editável? Não se preocupe com a rolagem, e o único JS que eu gosto é se você planeja salvar os dados em desfoque ... e, aparentemente, é compatível com todos os navegadores populares: http://caniuse.com/#feat = contenteditable

Basta estilizá-lo para parecer uma caixa de texto, e ele será redimensionado automaticamente ... Torne sua altura mínima a altura preferida do texto.

O interessante dessa abordagem é que você pode salvar e marcar em alguns 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>
Webmaster G
fonte
O Chrome adicionará elementos <div> no ENTER.
precisa saber é o seguinte
contenteditableé bom, mas se você quer texto simples, ele precisa de várias opções como -webkit-user-modify: read-write-plaintext-onlye white-space: pre-wrap.
Mk01aj 12/12
@_sbaechler: os <div> s são omitidos ao usar [dom-element].innerText. @WebmasterG IMHO, seria bom omitir o jquery (por transparência) e incluir o exemplo nesta página através do Snippet de código executável em vez de no jsfiddle.
adabru
4

Eu usei o seguinte código para várias áreas de texto. Funcionando bem no Chrome 12, Firefox 5 e IE 9, mesmo com as ações de excluir, cortar e colar executadas nas á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>
Nikunj Bhatt
fonte
4

Existe uma abordagem ligeiramente 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>

A idéia é copiar o texto textareapara o preCSS e deixar que ele tenha o mesmo tamanho.

O benefício é que as estruturas apresentam ferramentas simples para mover o texto sem tocar em nenhum evento. Ou seja, no AngularJS você adicionaria um ng-model="foo" ng-trim="false"ao textareae ng-bind="foo + '\n'"ao pre. Veja um violino .

Apenas certifique-se de que pretenha o mesmo tamanho de fonte que o textarea.

Karolis Juodelė
fonte
11
" Apenas certifique-se de que pretenha o mesmo tamanho de fonte que otextarea " - Eles precisam do mesmo line-heighte de uma quantidade igual paddinge / ou bordertambém. Esta é a melhor solução para Angular.
Jamie Barker
4

O seguinte funciona para recortar, colar etc., independentemente de essas ações serem do mouse, de um atalho de teclado, de uma opção na barra de menus ... várias respostas adotam uma abordagem semelhante, mas não levam em consideração dimensionamento, e é por isso que eles aplicam incorretamente o estilo overflow: hidden .

Eu faço o seguinte, que também funciona bem com max-heighte rowspara altura mínima e 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 uma integridade absoluta, você deve chamar a adjustfunção em mais algumas circunstâncias:

  1. Eventos de redimensionamento de janela, se a largura das textareaalterações for alterada com redimensionamento de janela ou outros eventos que alterem a largura da área de texto
  2. Quando o textarea's displaymudanças atributo de estilo, por exemplo, quando se vai de none(escondido) parablock
  3. Quando o valor de textareaé alterado programaticamente

Observe que usar window.getComputedStyleou obter currentStylepode ser um pouco caro computacionalmente; portanto, você pode querer armazenar em cache o resultado.

Funciona para o IE6, então eu realmente espero que seja bom o suficiente.

Joseph Nields
fonte
4

Como uma abordagem diferente, você pode usar um <span>que ajusta seu tamanho automaticamente. Você precisará torná-lo editável adicionando a contenteditable="true"propriedade e pronto:

div {
  width: 200px;
}

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

O único problema dessa abordagem é que, se você quiser enviar o valor como parte do formulário, precisará fazer isso sozinho em JavaScript. Fazer isso é relativamente fácil. Por exemplo, você pode adicionar um campo oculto e, no onsubmitcaso do formulário, atribuir o valor de spanao campo oculto, que será automaticamente enviado com o formulário.

Racil Hilan
fonte
Já existe uma resposta usando contenteditable nesta página: stackoverflow.com/questions/454202/…
adabru
@ adabru Sim, mas as duas respostas não são as mesmas. A Toyota fabrica carros vermelhos e a Ford também fabrica carros vermelhos, mas são diferentes, não são? Se você gosta mais da outra resposta, vá em frente. Mas há quem aprecie mais a minha resposta e a acompanhe. Ter opções diferentes é bom.
Racil Hilan
3

Um pouco de correções. Funciona perfeitamente no 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;
  });
artnik-pro
fonte
funciona desde que suas linhas não ultrapassem o limite - então elas não caberão.
Tomáš Kafka
funciona fora da caixa, ótimo (firefox 72)
Mikeys4u 18/01
2

Eu sei uma maneira curta e correta de implementar isso com jquery.Nenhuma div extra oculta é necessária e funciona na maioria dos 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>

fonte
O jQuery .live()foi descontinuado. api.jquery.com/live Você geralmente prefere usar .on().
27414 Luke
2

Não sei se alguém mencionou dessa maneira, mas em alguns casos é possível redimensionar a altura com linhas

textarea.setAttribute('rows',breaks);

Demo

h0mayun
fonte
11
Isso funciona apenas se você tiver white-space: nowrap;. Quando uma linha é agrupada em outra linha sem quebra de linha, a área de texto não será mais ajustada corretamente.
Yeti
2

Aqui está uma diretiva angularjs para a resposta do 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>
chrmcpn
fonte
Você deve usar $ timeout do que setTimout - isso garantirá que o modelo seja inicializado (não é necessário especificar milissegundos - ele será executado após o ciclo de resumo angular). Também elemento = elemento [0]; é uma prática muito ruim ... Enfim, a solução não é boa para mim, pois preciso que a área de texto seja uma linha até que haja mais texto.
Karol WebSky
2

Você pode usar o JQuery para expandir textareaenquanto digita:

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

Mauricio Sánchez
fonte
Solução mais limpa. mas como devemos parar de usar jQuery: textarea.addEventListener ('keyup', () => {textarea.style.height = 0; textarea.style.height = ${textarea.scrollHeight}px;});
Toni Michel Caubet 6/02/19
2

Aqueles que querem alcançar o mesmo em novas versões do Angular.

Pegue o elemento textAreaRef.

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

Também estou adicionando outro caso de uso que pode ser útil para alguns usuários que estão lendo o encadeamento, quando o usuário deseja aumentar a altura da área de texto para determinada altura e depois overflow:scrollusá-lo, o método acima pode ser estendido para alcançar o 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';
    }
  }
Divyanshu Rawat
fonte
1

Algumas das respostas aqui não são responsáveis ​​pelo preenchimento.

Supondo que você tenha um maxHeight que você não deseja repassar, isso funcionou para mim:

    // 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);
hasen
fonte
1

Uma abordagem ainda mais simples e limpa é a seguinte:

// 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 o 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
}

Tudo o que é necessário é adicionar a .auto-heightclasse à que textareavocê deseja atingir.

Testado em FF, Chrome e Safari. Deixe-me saber se isso não funcionar para você, por qualquer motivo. Mas, essa é a maneira mais limpa e simples de descobrir que isso funciona. E funciona muito bem! : D

reviver
fonte
Você tentou remover o texto após a edição? A área de texto entrou em colapso?
18C
1

Esse código funciona para colar e selecione excluir também.

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>

Aqui está o JSFiddle

Kurenai Kunai
fonte
1

Eu recomendo a biblioteca javascript em http://javierjulio.github.io/textarea-autosize .

Por comentários, adicione um exemplo de código de bloqueio no uso de plug-ins:

<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 necessário:

textarea {
  box-sizing: border-box;
  max-height: 160px; // optional but recommended
  min-height: 38px;
  overflow-x: hidden; // for Firefox (issue #5)
}
orange01
fonte
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();
}
Igor Krupitsky
fonte
1

Nenhuma das respostas parece funcionar. Mas este funciona para mim: https://coderwall.com/p/imkqoq/resize-textarea-to-fit-content

$('#content').on( 'change keyup keydown paste cut', 'textarea', function (){
    $(this).height(0).height(this.scrollHeight);
}).find( 'textarea' ).change();
Kim Homann
fonte
Essa deve ser a resposta aceita, embora seja o suficiente para ouvir eventos "keyup"
Bob Ross
1

minha implementação é muito simples, conte o número de linhas na entrada (e no mínimo 2 linhas para mostrar que é uma área de texto):

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

exemplo de trabalho completo com estímulo: https://jsbin.com/kajosolini/1/edit?html,js,output

(e isso funciona com o identificador de redimensionamento manual do navegador, por exemplo)

localhostdotdev
fonte
2
Isso só funciona se você quebrar a linha pressionando "enter". Se o texto for maior que a largura da área de texto, mas você não clicar em "enter", ele não será expandido.
Nathalia Xavier
1

A resposta aceita está funcionando bem. Mas isso é muito código para essa funcionalidade simples. O código abaixo fará o truque.

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

Aqui está o que eu fiz ao usar o MVC HTML Helper para TextArea. Eu tinha vários elementos da área de texto, então tive que distingui-los usando o ID do modelo.

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

e no script adicionou isso:

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

Eu testei no IE10 e Firefox23

gunnerz
fonte
0

Você pode 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();
Darex1991
fonte