461 votes

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

Il y avait un autre sujet à ce sujet que j'ai essayé. Mais il y a un problème : le textarea ne rétrécit pas si vous supprimez le contenu. Je n'arrive pas à trouver un moyen de le réduire à la bonne taille. clientHeight revient avec la taille complète de l'image textarea et non 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 )
    };
}

0 votes

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 leur suppression la rétrécit. Quel navigateur utilisez-vous ?

3 votes

Ma fonction fait une erreur. Il est nécessaire de taper une nouvelle ligne à la fin de la ligne. Voici une meilleure solution. james.padolsey.com/javascript/jquery-plugin-autoresize

0 votes

Vous pouvez essayer mon plugin pour cela : github.com/AndrewDryga/jQuery.Textarea.Autoresize

272voto

panzi Points 2061

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 avec une seule ligne et ne grandit que la quantité exacte nécessaire. Il est acceptable pour une seule textarea mais j'ai voulu écrire quelque chose où j'aurais beaucoup beaucoup de ces choses. textarea (à peu près autant qu'il y a normalement de lignes dans un grand document texte). Dans ce cas, c'est vraiment lent (dans Firefox, c'est follement lent). J'aimerais donc vraiment une approche qui utilise du CSS pur. Cela serait possible avec contenteditable mais je veux qu'il soit en clair.

0 votes

Malheureusement, cette méthode échoue dans IE8 et, comme elle utilise overflow : hidden, les utilisateurs d'IE n'ont aucun plan de secours. Vous pouvez activer et désactiver le débordement pour résoudre ce problème, mais la barre de défilement perd alors la tête. Si vous n'utilisez pas overflow : hidden, la zone de texte ne rétrécit pas. Fermez quand même !

0 votes

@ChrisMoschini J'ai modifié un peu le code. Est-ce que cela fonctionne pour vous ?

0 votes

En utilisant IE tester, le code ci-dessus fonctionne même avec IE 5.5. Je n'ai pas testé avec IE 9 car je n'ai que XP d'installé dans ma VirtualBox.

68voto

chim Points 1799

Solution jQuery adapter le css à 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 fiddle avec le style minimum absolu comme point de départ pour vos expériences... http:/

5 votes

C'est bien, mais j'ajouterais overflow-y: hidden; à la css pour éviter que la barre de défilement ne clignote brièvement lors d'un redimensionnement.

0 votes

Je ne suis pas tout à fait sûr, mais sans elle, la zone de texte s'agrandit trop. Je pense que c'est lié à la façon dont est calculé le scrollHeight des éléments.

0 votes

J'aime beaucoup cette solution, mais dans le premier exemple, comment pourrais-je limiter le nombre de rangées et me débarrasser du remplissage ?

32voto

GijsjanB Points 2604
<!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 des balises style et script, mais cela devient un peu désordonné à mon avis (c'est de l'ancien style HTML+JS et ce n'est pas encouragé).

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

Edit : code modernisé. Changement de l'attribut onkeyup en addEventListener.
Edit : keydown fonctionne mieux que keyup
Edit : déclarer la fonction avant de l'utiliser
Edit : l'entrée fonctionne mieux que la descente (thnx @WASD42 & @MA-Maddin)

jsfiddle

3 votes

Celle-ci présente quelques inconvénients : 1) La zone de texte ne sera pas redimensionnée si l'utilisateur colle quelque chose uniquement avec les boutons de la souris ; 2) Si l'utilisateur colle quelque chose en utilisant le 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 sera agrandie qu'après la dernière pression. Vous devriez également ajouter la même fonction aux événements coller, couper, modifier et déposer.

0 votes

Il suffit donc d'utiliser le input à la place. Voir stackoverflow.com/a/14029861/1951524

0 votes

Version améliorée avec plusieurs textarea en une seule phrase : document.querySelectorAll('textarea').forEach(function(te){ te.addEventListener("input", function() { this.style.height='24px'; this.style.height=this.scrollHeight+12+'px'; }); });

19voto

Si vous n'avez pas besoin de prendre en charge IE8, vous pouvez utiliser la fonction 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));
}

Il ne vous reste plus qu'à ajouter quelques CSS et le tour est joué :

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

Utilisation :

<textarea autoresize>Type here and I’ll resize.</textarea>

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

1 votes

Belle solution, mais besoin de petites corrections. Lorsque le contenu de la zone de texte est chargé, par exemple à partir de la base de données, la zone de texte reste petite. Vous devez déclencher input événement pendant l'initialisation dans le cycle foreach.

17voto

bobince Points 270740

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

En général, vous ne devriez pas vraiment compter sur scrollHeight pour les contrôles de formulaires. En dehors du fait que scrollHeight est traditionnellement moins bien supporté que certaines des autres extensions d'IE, HTML/CSS ne dit rien sur la façon dont les contrôles de formulaires sont implémentés en interne et vous n'avez aucune garantie que scrollHeight sera quelque chose de significatif. (Traditionnellement, certains navigateurs ont utilisé des widgets d'OS pour cette tâche, rendant impossible toute interaction CSS et DOM sur leurs internes). Vérifiez au moins l'existence de scrollHeight/clientHeight avant d'essayer d'activer l'effet.

Une autre approche possible pour éviter le problème, s'il est important que cela fonctionne plus largement, pourrait être d'utiliser un div caché de la même largeur que la zone de texte, avec la même police. Au moment du keyup, vous copiez le texte de la zone de texte dans un nœud de texte de la division cachée (en n'oubliant pas de remplacer ' \n avec un saut de ligne, et échappez '<'/'&' correctement si vous utilisez innerHTML). Ensuite, il suffit de mesurer le offsetHeight de la div pour obtenir la hauteur dont vous avez besoin.

1 votes

Quels sont les navigateurs qui sont censés avoir des problèmes avec scrollHeight pour les zones de texte ? Fonctionne bien avec les versions actuelles d'IE, Firefox et Opera...

1 votes

Le seul que j'ai sous la main est Konqueror, qui renvoie le clientHeight comme scrollHeight. C'est un comportement auquel on peut s'attendre à moins que le navigateur n'applique le modèle de boîte CSS aux éléments internes des widgets, ce qu'il n'a pas toujours fait et ce que la norme ne dit pas qu'il doit faire.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X