Création d'une zone de texte avec redimensionnement automatique

367

Il y avait un autre fil à ce sujet , que j'ai essayé. Mais il y a un problème: le textareane rétrécit pas si vous supprimez le contenu. Je ne trouve aucun moyen de le réduire à la bonne taille - la clientHeightvaleur revient en tant que taille réelle de textarea, pas son contenu.

Le code de cette page est ci-dessous:

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 )
    };
}
Chèvre mécontente
la source
La réponse acceptée pour le fil que vous avez lié fonctionne pour moi. L'ajout de sauts de ligne agrandit la zone de texte et les supprime réduit la zone de texte. Quel navigateur utilisez-vous?
EndangeredMassa
3
Ma fonction fait une erreur. Il faut nécessairement taper une nouvelle ligne en fin de ligne. C'est une meilleure solution. james.padolsey.com/javascript/jquery-plugin-autoresize
Vous pouvez essayer mon plugin pour cela: github.com/AndrewDryga/jQuery.Textarea.Autoresize
Andrew Dryga
copie possible de la zone de texte
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
J'ai créé un package pour cela si vous utilisez react
Martin Dawson

Réponses:

230

Cela fonctionne pour moi (Firefox 3.6 / 4.0 et Chrome 10/11):

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

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

Si vous voulez l'essayer sur jsfiddle Il commence par une seule ligne et ne fait croître que la quantité exacte nécessaire. C'est correct pour un single textarea, mais je voulais écrire quelque chose où j'aurais beaucoup beaucoup de tels textarea(environ autant que l'on aurait normalement des lignes dans un grand document texte). Dans ce cas, c'est vraiment lent. (Dans Firefox, c'est incroyablement lent.) Je voudrais donc vraiment une approche qui utilise du CSS pur. Cela serait possible aveccontenteditable , mais je veux que ce soit en clair uniquement.

panzi
la source
13
Cela fait! J'ai créé un jsfiddle pour vous: jsfiddle.net/CbqFv Il fonctionne maintenant dans Chrome, Firefox et IE8 - bien qu'il soit un peu délicat dans IE8. Lorsque vous augmentez ou diminuez le nombre de lignes, cela panique un peu. Comme vous l'avez peut-être vu dans le plugin de redimensionnement automatique pour jQuery, ils contournent cela en clonant la zone de texte, en définissant sa hauteur sur auto au lieu de l'original, puis en l'utilisant pour définir la hauteur de défilement sur l'original. Je l'ai fait dans ce violon mis à jour: jsfiddle.net/CbqFv/2 Il résout le problème IE mais Firefox cesse de fonctionner.
Chris Moschini
3
@HelenNeely: Alors n'utilisez pas d'identifiant. Par exemple, utilisez une classe et faites ce que init fait pour tous les éléments de cette classe. Cela devrait être une tâche pour les débutants.
panzi
3
@ DenilsonSá Si l'on pouvait seulement supposer que seuls les navigateurs modernes sont utilisés, le Web serait un meilleur endroit.
panzi
2
Cela ne fonctionnera pas bien si une barre de défilement est implémentée dans IE11. Si vous utilisez ce violon jsfiddle.net/CbqFv et entrez des lignes jusqu'à ce que vous ayez une barre de défilement, vous le verrez. Des idées?
kaljak
6
Cela casse complètement si la zone de texte est proche de la fin de la page inférieure - tout saute en avant et en arrière à cause de style.height='auto'. Je soupçonne que la solution consiste à ajouter un frère caché utilisé uniquement pour la mesure.
rr-
372

UNE SOLUTION COMPLÈTE ET SIMPLE

Mise à jour 2020-05-14 ( Prise en charge améliorée du navigateur pour les mobiles et les tablettes)

Le code suivant fonctionnera:

  • Sur entrée clé.
  • Avec du texte collé (clic droit & ctrl + v).
  • Avec du texte coupé (clic droit & ctrl + x).
  • Avec texte préchargé.
  • Avec toutes les zones de texte (zone de texte multiligne) .
  • Avec Firefox (testé v31-67).
  • Avec Chrome (testé v37-74).
  • Avec IE (testé v9-v11).
  • Avec Edge (testé v14-v18).
  • Avec IOS Safari .
  • Avec navigateur Android .
  • Avec JavaScript le mode strict .
  • Est w3c validé.
  • Et est rationalisé et efficace.

OPTION 1 (Avec jQuery)

Cette option nécessite jQuery et a été testée et fonctionne avec 1.7.2 - 3.3.1

Simple (ajoutez ce code jquery à votre fichier de script principal et oubliez-le.)

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


OPTION 2 (JavaScript pur)

Simple (Ajoutez ce JavaScript à votre fichier de script principal et oubliez-le.)

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


OPTION 3 (extension jQuery)

Utile si vous souhaitez appliquer un chaînage supplémentaire aux zones de texte que vous souhaitez redimensionner automatiquement.

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

Invoquer avec $('textarea').autoHeight()


MISE À JOUR DE TEXTAREA VIA JAVASCRIPT

Lors de l'injection de contenu dans une zone de texte via JavaScript, ajoutez le code suivant pour appeler la fonction de l'option 1.

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

PRESET TEXTAREA HEIGHT

Pour fixer la hauteur initiale de la zone de texte, vous devrez ajouter une condition supplémentaire:

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
la source
12
C'est une excellente solution, il serait légèrement plus compréhensible que le nom de la méthode et le nom du paramètre soient mis à jour pour être de vrais noms au lieu de lettres individuelles.
Chris Marisic
5
@Obsidian Merci! Je viens de comprendre pourquoi j'obtiens toujours un 0 —— J'ai mis la zone de texte dans un modal Bootstrap! Comme le modal est caché au début, la zone de texte aura un scrollHeight 0
WTIFS
7
@Obsidian Fantastic !! (Option 3). C'est this.style.height = 'auto';la correction magique du comportement. J'étais tellement frustré pourquoi le scrollHeight était si bizarre dans son comportement. La hauteur en auto, puis en faisant correspondre le scrollHeight dans le même cycle de rendu me fait toujours remarquer comment cela «résout» ce problème, même s'il ne devrait être techniquement que la deuxième hauteur.
bits sans bit
2
J'ai essayé l'option 3 dans Chrome aujourd'hui et j'ai dû faire quelques ajustements. 1) Il ne sera pas toujours redimensionné correctement si vous avez une transition "hauteur" ou "tout" sur la zone de texte. Je recommande de ne pas utiliser de transitions qui affectent la hauteur. 2) Le scrollHeight renvoyait un minimum de deux lignes de hauteur (peut-être parce que c'est la valeur par défaut pour les zones de texte dans Chrome) mais si vous modifiez this.style.height = 'auto'; à this.style.height = '0px'; et ajoutez une hauteur minimale pour éviter que l'état initial ne passe réellement à 0, scrollHeight renverra correctement une ligne de hauteur le cas échéant.
ZorroDeLaArena
3
@Obsidian Pouvez-vous expliquer comment this.style.height = 'auto';corrige le comportement de scrollHeight? C'est juste magique.
sidney
63

La solution jQuery ajuste le CSS pour l'adapter à vos besoins

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

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

J'ai créé un violon avec le style minimum absolu comme point de départ pour vos expériences ... http://jsfiddle.net/53eAy/951/

chim
la source
5
C'est bien, mais j'ajouterais overflow-y: hidden;au CSS pour empêcher la barre de défilement de clignoter brièvement lors du redimensionnement.
brettjonesdev
Pas tout à fait sûr, mais sans cela, la zone de texte augmente trop. Je pense que cela a à voir avec la façon dont les éléments scrollHeight sont calculés.
chim
1
Utilisez plusieurs événements pour faire fonctionner une grande vérité du scénario $('textarea.auto-resize').on('change cut paste drop keyup', function(){...})
raxith
1
Saute comme un fou dans Chrome 40 Win 8.1 sur des textes plus longs que la fenêtre d'affichage. Le rend tout à fait inutilisable.
tobibeer
1
Maintenir la touche Entrée (nouvelle ligne) entraîne le défilement. La taille ne s'ajuste que lorsque la touche est relâchée.
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>

Testé dans Firefox 14 et Chromium 18. Les nombres 24 et 12 sont arbitraires, testez pour voir ce qui vous convient le mieux.

Vous pourriez vous passer du style et des balises de script, mais cela devient un peu désordonné (c'est du HTML + JS à l'ancienne et ce n'est pas recommandé).

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

Edit: code modernisé. Attribut onkeyup modifié en addEventListener.
Edit: keydown fonctionne mieux que keyup
Edit: declare function avant d'utiliser
Edit: input fonctionne mieux que keydown (thnx @ WASD42 & @ MA-Maddin)

jsfiddle

GijsjanB
la source
3
Celui-ci présente certains inconvénients: 1) La zone de texte ne serait pas redimensionnée, l'utilisateur ne peut alors coller quelque chose qu'avec les boutons de sa souris; 2) Si l'utilisateur colle quelque chose à l'aide du clavier (Ctrl + V), la zone de texte ne sera redimensionnée que lorsqu'il relâchera Ctrl. Si l'utilisateur appuie plusieurs fois sur Ctrl + V, la zone de texte ne s'agrandira qu'après la dernière. Vous devez également ajouter la même fonction pour coller, couper, modifier et supprimer des événements.
WASD42
Il vous suffit donc d'utiliser l' inputévénement à la place. Voir stackoverflow.com/a/14029861/1951524
Martin Schneider
Version améliorée avec textareaprise en charge multiple en une ligne:document.querySelectorAll('textarea').forEach(function(te){ te.addEventListener("input", function() { this.style.height='24px'; this.style.height=this.scrollHeight+12+'px'; }); });
Meisner
1
@Meisner C'est plus court, mais je ne dirais pas que c'est "amélioré". Avec une fonction anonyme, il n'y a aucun moyen d'appeler removeEventListeneret de nettoyer vos auditeurs d'événements. Ceci est particulièrement important lors de la création d'écouteurs d'événements partout dans une boucle forEach. De plus, à mon avis, la lisibilité est beaucoup plus importante que la concision.
GijsjanB
pour les autres et pour l'avenir, assurez-vous que la box-sizing: border-box;propriété est définie, sinon la zone de texte explose de 4 pixels pour chaque événement onInput. J'ai passé environ 3 heures jusqu'à ce que je comprenne que c'était le problème.
AIon
24

La meilleure solution (qui fonctionne et est courte) pour moi est:

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

Il fonctionne comme un charme sans aucun clignement de pâte (avec la souris également), coupe, entre et rétrécit à la bonne taille.

Veuillez jeter un œil à jsFiddle .

vatavale
la source
Terrifiant!!! une offre en ligne! question stupide ho je peux ajouter une animation quand il redimensionne? comme la zone de texte qui se redimensionne doucement plutôt que le saut à la taille?
user2513846
1
@ user2513846 Il semble que ce ne soit pas possible par la conception de l'édition multi-lignes. J'ai fait un exemple d'animation de la taille d'une zone de texte: jsfiddle.net/yk2g333e Comme vous le savez, le curseur de texte descend au niveau de et de la ligne ou du curseur, donc s'il n'y a pas de pause à ce moment, il n'y a rien à animer. Mais une pause sera ennuyeuse pour l'utilisateur.
vatavale
1
@ user2513846 Cependant, avec une ligne vide de plus à la fin de la zone de texte, il est possible d'avoir une animation fluide: jsfiddle.net/p23erdfr
vatavale
16

Vous utilisez la valeur plus élevée du clientHeight actuel et du scrollHeight de contenu. Lorsque vous réduisez le scrollHeight en supprimant le contenu, la zone calculée ne peut pas devenir plus petite car le clientHeight, précédemment défini par style.height, le maintient ouvert. Vous pouvez plutôt prendre un max () de scrollHeight et une valeur de hauteur minimale que vous avez prédéfinie ou calculée à partir de textarea.rows.

En général, vous ne devriez probablement pas vraiment compter sur scrollHeight sur les contrôles de formulaire. À part que scrollHeight est traditionnellement moins largement pris en charge que certaines des autres extensions IE, HTML / CSS ne dit rien sur la façon dont les contrôles de formulaire sont implémentés en interne et vous n'êtes pas assuré que scrollHeight sera significatif. (Traditionnellement, certains navigateurs ont utilisé des widgets de système d'exploitation pour la tâche, rendant impossible l'interaction CSS et DOM sur leurs internes.) Au moins, reniflez l'existence de scrollHeight / clientHeight avant d'essayer d'activer l'effet.

Une autre approche alternative possible pour éviter le problème s'il est important que cela fonctionne plus largement pourrait être d'utiliser une div masquée de la même largeur que la zone de texte et définie dans la même police. Lors de la manipulation, vous copiez le texte de la zone de texte vers un nœud de texte dans div masqué (en vous souvenant de remplacer '\ n' par un saut de ligne et d'échapper '<' / '&' correctement si vous utilisez innerHTML). Il suffit ensuite de mesurer l'offset du div. La hauteur vous donnera la hauteur dont vous avez besoin.

bobince
la source
1
Quels navigateurs sont censés avoir des problèmes avec les scrollHeightzones de texte? Fonctionne très bien avec les versions actuelles d'IE, Firefox et Opera ...
Christoph
1
Le seul que j'ai à remettre est Konqueror, qui renvoie le clientHeight comme scrollHeight. C'est un comportement auquel vous pouvez vous attendre, sauf si le navigateur applique le modèle de boîte CSS aux composants internes des widgets, ce qu'ils n'ont pas toujours fait et la norme ne dit pas qu'ils doivent le faire.
bobince
14

Si vous n'avez pas besoin de prendre en charge IE8, vous pouvez utiliser l' inputévénement:

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

Maintenant, il vous suffit d'ajouter du CSS et vous avez terminé:

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

Usage:

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

Vous pouvez en savoir plus sur son fonctionnement sur mon article de blog .

Maximilian Hoffmann
la source
1
Belle solution, mais besoin de peu de correctifs. Lorsque le contenu de la zone de texte est chargé f.ex. à partir de la base de données, la zone de texte reste petite. Vous devez déclencher un inputévénement lors de l'initialisation dans chaque cycle.
Ajax
11

redimensionnement automatique

https://github.com/jackmoore/autosize

Just works, autonome, est populaire (3.0k + étoiles GitHub en octobre 2018), disponible sur cdnjs ) et léger (~ 3.5k). Démo:

<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, si vous utilisez l'éditeur ACE, utilisez maxLines: Infinity: Ajuster automatiquement la hauteur au contenu dans l'éditeur Ace Cloud 9

Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
la source
2
La version 2 est sortie en février 2015. Elle est devenue plus simple et ne dépend plus de jQuery
croustillant
Désolé, ça marche. Peut-être que j'étais dans un autre navigateur .. donc, je pense que c'est mieux si vous ignorez mon commentaire ..
Toni Michel Caubet
@ToniMichelCaubet ah, OK peut-être alors un problème CDN. Laisse moi vérifier.
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
Le autosizeplugin ne permet pas de redimensionner manuellement en utilisant l'icône de redimensionnement dans la zone de texte.
j4v1
7

J'ai trouvé un paquebot d' ici ;

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

Quelqu'un a-t-il considéré que le contenu pouvait être modifié? Pas de problème avec le défilement, et le seul JS que j'aime à ce sujet est si vous prévoyez d'enregistrer les données sur le flou ... et apparemment, il est compatible avec tous les navigateurs populaires: http://caniuse.com/#feat = contenteditable

Il suffit de le styliser pour qu'il ressemble à une zone de texte, et il se redimensionne automatiquement ... Définissez sa hauteur minimale comme la hauteur de texte préférée et définissez-la.

Ce qui est cool avec cette approche, c'est que vous pouvez enregistrer et étiqueter sur certains navigateurs.

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
la source
Chrome ajoutera des éléments <div> sur ENTER.
sbaechler
contenteditableest bon, mais si vous voulez du texte en clair, il a besoin d'un tas d'options comme -webkit-user-modify: read-write-plaintext-onlyet white-space: pre-wrap.
mik01aj
@_sbaechler: les <div> sont omis lors de l'utilisation [dom-element].innerText. @WebmasterG À mon humble avis, il serait bien d'omettre jquery (pour la transparence) et d'inclure l'exemple sur cette page via un extrait de code exécutable au lieu de jsfiddle.
adabru
4

J'ai utilisé le code suivant pour plusieurs zones de texte. Fonctionne très bien dans Chrome 12, Firefox 5 et IE 9, même avec des actions de suppression, de couper-coller effectuées dans les zones de texte.

<!-- 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
la source
4

Il existe une approche légèrement différente.

<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'idée est de copier le texte de textareadans preet de laisser CSS s'assurer qu'ils ont la même taille.

L'avantage est que les frameworks présentent des outils simples pour déplacer du texte sans toucher à aucun événement. À savoir, dans AngularJS, vous ajouteriez un ng-model="foo" ng-trim="false"au textareaet ng-bind="foo + '\n'"au pre. Voir un violon .

Assurez-vous simplement qu'il prea la même taille de police que le textarea.

Karolis Juodelė
la source
1
" Assurez-vous simplement qu'il prea la même taille de police que letextarea " - Ils ont besoin du même line-height, et d'une quantité égale de paddinget / ou bordertrop. C'est la meilleure solution pour Angular.
Jamie Barker
4

Les travaux suivants permettent de couper, coller, etc., indépendamment du fait que ces actions proviennent de la souris, d'un raccourci clavier, de la sélection d'une option dans une barre de menus ... plusieurs réponses adoptent une approche similaire mais ne tiennent pas compte de la boîte - dimensionnement, c'est pourquoi ils appliquent incorrectement le style overflow: hidden .

Je fais ce qui suit, qui fonctionne également bien avec max-heightet rowspour une hauteur minimale et maximale.

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>

Pour être complet, vous devez appeler la adjustfonction dans quelques circonstances supplémentaires:

  1. Événements de redimensionnement de la fenêtre, si la largeur des textareamodifications avec le redimensionnement de la fenêtre ou d'autres événements qui modifient la largeur de la zone de texte
  2. Lorsque l' attribut style de textarea's displaychange, par exemple quand il passe de none(caché) àblock
  3. Lorsque la valeur de la textareaest modifiée par programme

Notez que l'utilisation window.getComputedStyleou l'obtention currentStylepeut être quelque peu coûteuse en termes de calcul, vous pouvez donc vouloir mettre le résultat en cache à la place.

Fonctionne pour IE6, donc j'espère vraiment que ce support est assez bon.

Joseph Nields
la source
4

Comme approche différente, vous pouvez utiliser un <span>qui ajuste automatiquement sa taille. Vous devrez la rendre modifiable en ajoutant la contenteditable="true"propriété et vous avez terminé:

div {
  width: 200px;
}

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

Le seul problème avec cette approche est que si vous souhaitez soumettre la valeur dans le cadre du formulaire, vous devrez le faire vous-même en JavaScript. Cela est relativement facile. Par exemple, vous pouvez ajouter un champ masqué et dans le onsubmitcas du formulaire attribuer la valeur de la spanau champ masqué qui sera ensuite automatiquement soumis avec le formulaire.

Racil Hilan
la source
Il y a déjà une réponse en utilisant contenteditable sur cette page: stackoverflow.com/questions/454202/…
adabru
@adabru Oui, mais les deux réponses ne sont pas les mêmes. Toyota fabrique des voitures rouges et Ford fabrique également des voitures rouges, mais elles sont différentes, n'est-ce pas? Si vous préférez l'autre réponse, allez-y. Mais il y a ceux qui apprécient davantage ma réponse et la suivent. Avoir différentes options, c'est bien.
Racil Hilan
3

Un peu de corrections. Fonctionne parfaitement dans 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
la source
fonctionne tant que vos lignes ne débordent pas - alors elles ne rentreront pas.
Tomáš Kafka
fonctionne hors de la boîte, grand (firefox 72)
Mikeys4u
2

Je connais un moyen court et correct de l'implémenter avec jquery.Aucun div caché supplémentaire n'est nécessaire et fonctionne dans la plupart des navigateurs

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

la source
jQuery .live()est obsolète. api.jquery.com/live Vous voudrez généralement utiliser à la .on()place.
Luke
2

Je ne sais pas si quelqu'un mentionne cette façon, mais dans certains cas, il est possible de redimensionner la hauteur avec des lignes Attribut

textarea.setAttribute('rows',breaks);

Démo

h0mayun
la source
1
Cela ne fonctionne que si vous en avez white-space: nowrap;. Lorsqu'une ligne passe à une autre ligne sans saut de ligne, la zone de texte ne sera plus ajustée correctement.
Yeti
2

Voici une directive angularjs pour la réponse de panzi.

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

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

HTML:

<textarea ng-model="foo" auto-height></textarea>
chrmcpn
la source
Vous devriez plutôt utiliser $ timeout que setTimout - cela garantira que le modèle sera initialisé (pas besoin de spécifier des millisecondes - il sera exécuté après le cycle de résumé angulaire). Aussi élément = élément [0]; est une très mauvaise pratique ... Quoi qu'il en soit, la solution n'est pas bonne pour moi car j'ai besoin que la zone de texte soit sur une ligne jusqu'à ce qu'il y ait plus de texte.
Karol Websky,
2

Vous pouvez utiliser JQuery pour développer le textareatout en tapant:

$(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
la source
Solution la plus propre. mais comme nous devrions arrêter d'utiliser jQuery: textarea.addEventListener ('keyup', () => {textarea.style.height = 0; textarea.style.height = ${textarea.scrollHeight}px;});
Toni Michel Caubet
2

Ceux qui veulent obtenir le même résultat dans les nouvelles versions d'Angular.

Saisissez l'élément 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>

J'ajoute également un autre cas d'utilisation qui peut être utile pour certains utilisateurs qui lisent le fil, lorsque l'utilisateur souhaite augmenter la hauteur de la zone de texte à une certaine hauteur, puis l'afficher overflow:scroll, la méthode ci-dessus peut être étendue pour atteindre le cas d'utilisation mentionné.

  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
la source
1

Certaines des réponses ici ne tiennent pas compte du remplissage.

En supposant que vous avez un maxHeight que vous ne voulez pas dépasser, cela a fonctionné pour moi:

    // 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
la source
1

Une approche encore plus simple et plus propre est la suivante:

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

// et le 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
}

Il suffit d'ajouter la .auto-heightclasse à touttextarea suffit vous souhaitez cibler.

Testé dans FF, Chrome et Safari. Faites-moi savoir si cela ne fonctionne pas pour vous, pour quelque raison que ce soit. Mais, c'est la manière la plus propre et la plus simple que j'ai trouvée que cela fonctionne. Et ça marche très bien! :RÉ

relancer
la source
Avez-vous essayé de supprimer du texte après la modification? La zone de texte s'est-elle effondrée?
18
1

Ce code fonctionne pour coller et sélectionnez supprimer également.

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>

Voici le JSFiddle

Kurenai Kunai
la source
1

Je recommande la bibliothèque javascript de http://javierjulio.github.io/textarea-autosize .

Par commentaires, ajoutez un exemple de bloc de code sur l'utilisation du plugin:

<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 minimum requis:

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

MakeTextAreaResisable qui utilise 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
la source
1

Aucune des réponses ne semble fonctionner. Mais celui-ci fonctionne pour moi: 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
la source
Cela devrait être la réponse acceptée, mais il suffit d'écouter les événements de "keyup"
Bob Ross
1

mon implémentation est très simple, comptez le nombre de lignes en entrée (et minimum 2 lignes pour montrer que c'est une zone de texte):

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

exemple de travail complet avec stimulus: https://jsbin.com/kajosolini/1/edit?html,js,output

(et cela fonctionne avec la poignée de redimensionnement manuel du navigateur par exemple)

localhostdotdev
la source
2
Cela ne fonctionne que si vous coupez la ligne en appuyant sur "Entrée". Si votre texte est plus long que la largeur de la zone de texte mais que vous n'appuyez pas sur "Entrée", il ne se développe pas.
Nathalia Xavier
1

La réponse acceptée fonctionne bien. Mais c'est beaucoup de code pour cette fonctionnalité simple. Le code ci-dessous fera l'affaire.

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

Voici ce que j'ai fait en utilisant MVC HTML Helper pour TextArea. J'avais pas mal d'éléments de zone de texte, j'ai donc dû les distinguer à l'aide de l'ID de modèle.

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

et dans le script a ajouté ceci:

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

Je l'ai testé sur IE10 et Firefox23

gunnerz
la source
0

Vous pouvez utiliser ce code:

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