Développer automatiquement une zone de texte à l'aide de jQuery

128

Comment puis-je agrandir automatiquement une zone de texte à l'aide de jQuery?

J'ai une zone de texte pour expliquer l'ordre du jour de la réunion, donc je veux développer cette zone de texte lorsque le texte de mon ordre du jour continue de s'agrandir cette zone de texte.

Piyush
la source
Je pense que textarea est autoexpandable.
andrew Sullivan
2
duplication possible de Searching for the Ultimate Resizing Textarea
rjmunro
Veuillez envisager de modifier votre question et de supprimer le mot «jQuery»
vsync

Réponses:

113

J'en ai essayé beaucoup et celui-ci est génial. Link est mort. Une version plus récente est disponible ici . Voir ci-dessous pour l'ancienne version.
Vous pouvez essayer en maintenant la touche Entrée enfoncée dans la zone de texte. Comparez l'effet avec l'autre plugin textarea à expansion automatique ...

modifier en fonction du commentaire

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

Remarque: vous devez inclure les fichiers js nécessaires ...

Pour éviter que la barre de défilement dans la zone de texte ne clignote pendant l'expansion / la contraction, vous pouvez également régler le overflowsur hidden:

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




Mettre à jour:

Le lien ci-dessus est rompu. Mais vous pouvez toujours obtenir les fichiers javascript ici .

Reigel
la source
si mon identifiant de zone de texte est txtMeetingAgenda, comment puis-je implémenter la propriété Auto textArea dans jquery
Piyush
ici cliquez sur l'événement est défini ou non
Piyush
tout est question de textarea mais qu'en est-il de textbox. Ce plugin fonctionne-t-il également pour textbox?
Piyush
1
ce plugin ne fonctionne pas bien, essayez la taille automatique, c'est bien mieux
julesbou
Cela ne fonctionne que dans un seul sens lorsque textarea se développe. Mais lorsque vous commencez à supprimer le texte, cela ne réduit pas automatiquement la hauteur.
ekashking
166

Si vous ne voulez pas de plugin, il existe une solution très simple

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

Voyez-le fonctionner dans un jsFiddle que j'ai utilisé pour répondre à une autre question textarea ici .

Pour répondre à la question de le faire à l'envers ou de le réduire lorsque le texte est supprimé: jsFiddle

Et si vous voulez un plugin

@Jason en a conçu un ici

SpYk3HH
la source
1
J'ai dû supprimer + parseFloat ($ (this) .css ("borderTopWidth")) + parseFloat ($ (this) .css ("borderBottomWidth")), sinon il boucle infiniment avec un textarea stylé avec bootstrap
blacelle
3
Version jQuery-less:if (this.clientHeight < this.scrollHeight) { this.style.height = this.scrollHeight + 'px'; }
Georgii Ivankin
3
@metakungfu Eh bien, au lieu de simplement voter contre, vous pouvez peut-être aider à améliorer la réponse. Je n'ai aucun moyen de tester le distributeur automatique de la merde de pomme et Safari pour Windows a été interrompu il y a longtemps. Je ne peux donc vraiment rien faire pour déterminer pourquoi cela ne fonctionnerait pas. Au niveau du code, il n'y a rien de mal avec cette solution. Êtes-vous sûr que c'est le code qui rompt et non le safari dans jsfiddle? le safari est assez difficile et le violon vient de subir une mise à jour majeure. Mayeb vous pouvez ouvrir dev con et fournir plus de détails?
SpYk3HH
1
a également besoin de textarea overflow-y réglé sur hidden pour empêcher le défilement clignotant
iulial
2
Si je veux supprimer les lignes ajoutées, la taille agrandie de la zone de texte reste la même, est-il possible qu'elle puisse également se redimensionner automatiquement?
Steven
33

Agrandit / rétrécit la zone de texte. Cette démo utilise jQuery pour la liaison d'événements, mais ce n'est en aucun cas un must.
( pas de support IE - IE ne répond pas au changement d'attribut des lignes )

PAGE DE DÉMO


HTML

<textarea class='autoExpand' rows='3' data-min-rows='3' placeholder='Auto-Expanding Textarea'></textarea>

CSS

textarea{  
  display:block;
  box-sizing: padding-box;
  overflow:hidden;

  padding:10px;
  width:250px;
  font-size:14px;
  margin:50px auto;
  border-radius:8px;
  border:6px solid #556677;
}

javascript (mis à jour)

$(document)
    .one('focus.textarea', '.autoExpand', function(){
        var savedValue = this.value;
        this.value = '';
        this.baseScrollHeight = this.scrollHeight;
        this.value = savedValue;
    })
    .on('input.textarea', '.autoExpand', function(){
        var minRows = this.getAttribute('data-min-rows')|0,
            rows;
        this.rows = minRows;
        rows = Math.ceil((this.scrollHeight - this.baseScrollHeight) / 16);
        this.rows = minRows + rows;
    });
vsync
la source
2
car le code doit attendre un peu que la lettre que vous avez tapée soit imprimée à l'intérieur de la zone de texte et donc modifier les dimensions de la zone de texte
vsync
1
Je vois, la solution est cassée lorsque le texte est copié (CTRL + V) à partir de n'importe quelle source. Bien que, si le texte est tapé manuellement, c'est génial et très fluide.
Satya Kalluri
1
@vsync: comment modifieriez-vous plusieurs zones de texte? C'est-à-dire que vous avez textarea1 et textarea2 et vous voulez permettre aux deux de grandir?
jmoreno
1
Cela devrait être la meilleure réponse! J'ai posté une question basée sur cela si quelqu'un est intéressé: stackoverflow.com/questions/29930300/…
gsamaras
1
@AllyMurray - Je suis allé maintenant et je l'ai mis à jour à 16 car il semble donner un meilleur résultat. et oui, c'est la hauteur de ligne attendue
vsync
20

Vous pouvez essayer celui-ci

$('#content').on('change keyup keydown paste cut', 'textarea', function () {
        $(this).height(0).height(this.scrollHeight);
    }).find('textarea').change();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="content">
  <textarea>How about it</textarea><br />
  <textarea rows="5">111111
222222
333333
444444
555555
666666</textarea>
</div>

reza.cse08
la source
si vous voulez obtenir le scrollHeight de $ (this), vous pouvez utiliser $ (this) .prop ('scrollHeight'); à la place;)
Samuel Vicent
3
il clignote à chaque saut de ligne
joe
11

Grâce à SpYk3HH, j'ai commencé avec sa solution et je l'ai transformée en cette solution, qui ajoute la fonctionnalité de réduction et est encore plus simple et plus rapide, je suppose.

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

Testé dans les navigateurs Chrome, Firefox et Android 2.3.3 actuels.

Vous pouvez voir des clignotements des barres de défilement dans certains navigateurs. Ajoutez ce CSS pour résoudre ce problème.

textarea{ overflow:hidden; }
drolex
la source
ça ne marche pas du tout: / chaque caractère que je tape, ça ajoute de la hauteur.
vsync
1
Cela fonctionne parfaitement pour moi! Il n'y a certainement rien dans le code simple pour faire ce que vous dites.
drolex
1
ouais je le vois maintenant, votre code doit avoir la ligne qui définit la hauteur à 30 au départ. c'est probablement un ilne inutile car il oblige le développeur à peaufiner le code, au lieu de comprendre le code et de l'adapter à la zone de texte,
vsync
1
C'est incorrect. Le développeur n'a pas besoin de modifier le code. Il est nécessaire de régler la hauteur à 30 et cela fonctionne pour tout. L'utilisateur ne voit jamais cela se produire. C'est ainsi qu'il est capable de réduire la zone de texte. Le code comprend et s'adapte à la zone de texte. C'est tout le point.
drolex
Vous avez raison. page de démonstration: jsbin.com/ObEcoza/2/edit (le réglage de la hauteur 1pxsemble être meilleur)
vsync
10

Pour définir une zone de texte extensible automatiquement, vous devez faire deux choses:

  1. Développez- le une fois que vous avez cliqué sur la touche Entrée à l'intérieur ou saisissez le contenu sur plusieurs lignes.
  2. Et réduisez- le au flou pour obtenir la taille réelle si l'utilisateur a entré des espaces blancs. ( Bonus )

Voici une fonction artisanale pour accomplir la tâche.

Fonctionne bien avec presque tous les navigateurs (<IE7) . Voici la méthode:

    //Here is an event to get TextArea expand when you press Enter Key in it.
    // intiate a keypress event
    $('textarea').keypress(function (e) {  
       if(e.which == 13)   {   
       var control = e.target;                     
       var controlHeight = $(control).height();          
      //add some height to existing height of control, I chose 17 as my line-height was 17 for the control    
    $(control).height(controlHeight+17);  
    }
    }); 

$('textarea').blur(function (e) {         
    var textLines = $(this).val().trim().split(/\r*\n/).length;      
    $(this).val($(this).val().trim()).height(textLines*17);
    });

ICI est un article à ce sujet.

ouvert et gratuit
la source
6

J'ai déjà utilisé le plugin jQuery Textarea Expander avec de bons résultats.

richsage
la source
1
Une zone de texte (élément de texte d'entrée que je présume) n'est pas multiligne. Utilisez une zone de texte mais stylisez-la de manière appropriée - lignes, colonnes, etc., puis utilisez le plugin de croissance automatique comme ci-dessus.
richsage
4

Tout le monde devrait essayer ce plugin jQuery: xautoresize-jquery . C'est vraiment bien et devrait résoudre votre problème.

danchoif2
la source
Celui-ci m'a donné les meilleurs résultats et est également facile à mettre en œuvre.
blitzkid
4
function autosize(textarea) {
    $(textarea).height(1); // temporarily shrink textarea so that scrollHeight returns content height when content does not fill textarea
    $(textarea).height($(textarea).prop("scrollHeight"));
}

$(document).ready(function () {
    $(document).on("input", "textarea", function() {
        autosize(this);
    });
    $("textarea").each(function () {
        autosize(this);
    });
});

(Cela ne fonctionnera pas dans Internet Explorer 9 ou version antérieure car il utilise l' inputévénement)

Benrwb
la source
dans mon projet, comme je suis en train de rendre des choses entières dans la page par Jquery et dactylographié, votre solution était le seul moyen que je puisse résoudre mon problème merci
Harry Sarshogh
3

Je viens de créer cette fonction pour développer les zones de texte sur pageload. Changez simplement eachen keyupet cela se produira lorsque la zone de texte est saisie.

// On page-load, auto-expand textareas to be tall enough to contain initial content
$('textarea').each(function(){
    var pad = parseInt($(this).css('padding-top'));
    if ($.browser.mozilla) 
        $(this).height(1);
    var contentHeight = this.scrollHeight;
    if (!$.browser.mozilla) 
        contentHeight -= pad * 2;
    if (contentHeight > $(this).height()) 
        $(this).height(contentHeight);
});

Testé dans Chrome, IE9 et Firefox. Malheureusement, Firefox a ce bogue qui renvoie la valeur incorrecte pour scrollHeight, donc le code ci-dessus contient une solution de contournement (hacky) pour cela.

Simon Est
la source
3

J'ai corrigé quelques bugs dans la réponse fournie par Reigel (la réponse acceptée):

  1. L'ordre dans lequel les entités html sont remplacées maintenant ne provoque pas de code inattendu dans l'élément shadow. (L'original a remplacé ">" par "& ampgt;", provoquant un mauvais calcul de la hauteur dans de rares cas)
  2. Si le texte se termine par une nouvelle ligne, l'ombre reçoit désormais un caractère supplémentaire "#", au lieu d'avoir une hauteur supplémentaire fixe, comme c'est le cas dans l'original.
  3. Le redimensionnement de la zone de texte après l'initialisation met à jour la largeur de l'ombre.
  4. word-wrap ajouté: mot de pause pour l'ombre, donc il se brise comme une zone de texte (forçant les pauses pour les mots très longs)

Il reste quelques problèmes concernant les espaces. Je ne vois pas de solution pour les espaces doubles, ils sont affichés sous forme d'espaces simples dans l'ombre (rendu html). Cela ne peut pas être résolu en utilisant & nbsp ;, car les espaces doivent se rompre. En outre, la zone de texte coupe une ligne après un espace, s'il n'y a pas de place pour cet espace, elle coupera la ligne à un point antérieur. Les suggestions sont les bienvenues.

Code corrigé:

(function ($) {
    $.fn.autogrow = function (options) {
        var $this, minHeight, lineHeight, shadow, update;
        this.filter('textarea').each(function () {
            $this = $(this);
            minHeight = $this.height();
            lineHeight = $this.css('lineHeight');
            $this.css('overflow','hidden');
            shadow = $('<div></div>').css({
                position: 'absolute',
                'word-wrap': 'break-word',
                top: -10000,
                left: -10000,
                width: $this.width(),
                fontSize: $this.css('fontSize'),
                fontFamily: $this.css('fontFamily'),
                lineHeight: $this.css('lineHeight'),
                resize: 'none'
            }).appendTo(document.body);
            update = function () {
                shadow.css('width', $(this).width());
                var val = this.value.replace(/&/g, '&amp;')
                                    .replace(/</g, '&lt;')
                                    .replace(/>/g, '&gt;')
                                    .replace(/\n/g, '<br/>')
                                    .replace(/\s/g,'&nbsp;');
                if (val.indexOf('<br/>', val.length - 5) !== -1) { val += '#'; }
                shadow.html(val);
                $(this).css('height', Math.max(shadow.height(), minHeight));
            };
            $this.change(update).keyup(update).keydown(update);
            update.apply(this);
        });
        return this;
    };
}(jQuery));
Carlo Roosen
la source
3

Code de SpYk3HH avec ajout pour la réduction de taille.

function get_height(elt) {
    return elt.scrollHeight + parseFloat($(elt).css("borderTopWidth")) + parseFloat($(elt).css("borderBottomWidth"));
}

$("textarea").keyup(function(e) {
    var found = 0;
    while (!found) {
        $(this).height($(this).height() - 10);
        while($(this).outerHeight() < get_height(this)) {
            $(this).height($(this).height() + 1);
            found = 1;
        };
    }
});
DSblizzard
la source
Avez-vous vu ma réponse avant la vôtre?
drolex
1
Votre solution ne me convient pas, il y a eu une erreur, je ne me souviens plus laquelle.
DSblizzard
2

Cela a mieux fonctionné pour moi:

$('.resiText').on('keyup input', function() { 
$(this).css('height', 'auto').css('height', this.scrollHeight + (this.offsetHeight - this.clientHeight));
});
.resiText {
    box-sizing: border-box;
    resize: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<textarea class="resiText"></textarea>

Nori
la source
2

Les gens semblent avoir des solutions très travaillées ...

Voici comment je fais:

  $('textarea').keyup(function()
  {
    var 
    $this  = $(this),
    height = parseInt($this.css('line-height'),     10),
    padTop = parseInt($this.css('padding-top'),     10),
    padBot = parseInt($this.css('padding-bottom'),  10);

    $this.height(0);

    var 
    scroll = $this.prop('scrollHeight'),
    lines  = (scroll  - padTop - padBot) / height;

    $this.height(height * lines);
  });

Cela fonctionnera avec de longues lignes, ainsi que des sauts de ligne .. grandit et rétrécit ..

super héros
la source
1

J'ai écrit cette fonction jquery qui semble fonctionner.

Cependant, vous devez spécifier min-height en css, et à moins que vous ne souhaitiez coder, il doit comporter deux chiffres. c'est-à-dire 12px;

$.fn.expand_ta = function() {

var val = $(this).val();
val = val.replace(/</g, "&lt;");
val = val.replace(/>/g, "&gt;");
val += "___";

var ta_class = $(this).attr("class");
var ta_width = $(this).width();

var min_height = $(this).css("min-height").substr(0, 2);
min_height = parseInt(min_height);

$("#pixel_height").remove();
$("body").append('<pre class="'+ta_class+'" id="pixel_height" style="position: absolute; white-space: pre-wrap; visibility: hidden; word-wrap: break-word; width: '+ta_width+'px; height: auto;"></pre>');
$("#pixel_height").html(val);

var height = $("#pixel_height").height();
if (val.substr(-6) == "<br />"){
    height = height + min_height;
};
if (height >= min_height) $(this).css("height", height+"px");
else $(this).css("height", min_height+"px");
}
Davie Dave
la source
1

Pour toute personne utilisant le plugin publié par Reigel, sachez que cela désactivera la fonctionnalité d'annulation dans Internet Explorer (allez essayer la démo).

Si cela pose un problème pour vous, je vous suggère d'utiliser le plugin posté par @richsage à la place, car il ne souffre pas de ce problème. Voir le deuxième point sur la recherche de la zone de texte ultime de redimensionnement pour plus d'informations.

user1018494
la source
1

Je voulais des animations et une réduction automatique. La combinaison est apparemment difficile, car les gens ont proposé des solutions assez intenses pour cela. Je l'ai également rendu résistant aux zones de texte multiples. Et ce n'est pas aussi ridiculement lourd que le plugin jQuery.

Je me suis basé sur la réponse de vsync (et sur l'amélioration qu'il a apportée), http://codepen.io/anon/pen/vlIwj est le codepen de mon amélioration.

HTML

<textarea class='autoExpand' rows='3' data-min-rows='3' placeholder='Auto-Expanding Textarea'></textarea>

CSS

body{ background:#728EB2; }

textarea{  
  display:block;
  box-sizing: padding-box;
  overflow:hidden;

  padding:10px;
  width:250px;
  font-size:14px;
  margin:50px auto;
  border-radius:8px;
  border:6px solid #556677;
  transition:all 1s;
  -webkit-transition:all 1s;
}

JS

var rowheight = 0;

$(document).on('input.textarea', '.autoExpand', function(){
    var minRows = this.getAttribute('data-min-rows')|0,
        rows    = this.value.split("\n").length;
    $this = $(this);
    var rowz = rows < minRows ? minRows : rows;
    var rowheight = $this.attr('data-rowheight');
    if(!rowheight){
      this.rows = rowz;
      $this.attr('data-rowheight', (this.clientHeight  - parseInt($this.css('padding-top')) - parseInt($this.css('padding-bottom')))/ rowz);
    }else{
      rowz++;
      this.style.cssText = 'height:' + rowz * rowheight + 'px'; 
    }
});
Lodewijk
la source
Remarque: j'ai remarqué que cela fonctionne parfois mieux avec box-sizing: content-box. Je ne suis pas tout à fait sûr de savoir pourquoi, il devrait traiter correctement le remplissage :(
Lodewijk
1

Il y a beaucoup de réponses à cela, mais j'ai trouvé quelque chose de très simple, attachez un événement keyup à la zone de texte et vérifiez si la touche Entrée appuyez sur le code de la touche est 13

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

Cela ajoutera une autre ligne à votre zone de texte et vous pourrez styliser la largeur en utilisant CSS.

Prostil Hardi
la source
1

Disons que vous essayez d'accomplir cela en utilisant Knockout ... voici comment:

En page:

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

Dans le modèle de vue:

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

Cela devrait fonctionner même si vous avez plusieurs zones de texte créées par un Knockout foreach comme je le fais.

Barry Franklin
la source
1

Solution simple:

HTML:

<textarea class='expand'></textarea>

JS:

$('textarea.expand').on('input', function() {
  $(this).scrollTop($(this).height());
});
$('textarea.expand').scroll(function() {
  var h = $(this).scrollTop();
  if (h > 0)
    $(this).height($(this).height() + h);
});

https://fiddle.jshell.net/7wsnwbzg/

Pablo Werlang
la source
1

La solution la plus simple:

html:

<textarea class="auto-expand"></textarea>

css:

.auto-expand {
    overflow:hidden;
    min-height: 80px;
}

js (jquery):

$(document).ready(function () {
 $("textarea.auto-expand").focus(function () {
        var $minHeight = $(this).css('min-height');
        $(this).on('input', function (e) {
            $(this).css('height', $minHeight);
            var $newHeight = $(this)[0].scrollHeight;
            $(this).css('height', $newHeight);
        });
    });       
});
Katya Dolgov
la source
1

Solution avec pur JS

function autoSize() {
  if (element) {
    element.setAttribute('rows', 2) // minimum rows
    const rowsRequired = parseInt(
      (element.scrollHeight - TEXTAREA_CONFIG.PADDING) / TEXTAREA_CONFIG.LINE_HEIGHT
    )
    if (rowsRequired !== parseInt(element.getAttribute('rows'))) {
      element.setAttribute('rows', rowsRequired)
    }
  }
}

https://jsfiddle.net/Samb102/cjqa2kf4/54/

samb102
la source
1

C'est la solution que j'ai fini par utiliser. Je voulais une solution en ligne, et cela semble jusqu'à présent fonctionner très bien:

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

function autoResizeTextarea() {
  for (let index = 0; index < $('textarea').length; index++) {
    let element = $('textarea')[index];
    let offset = element.offsetHeight - element.clientHeight;
    $(element).css('resize', 'none');
    $(element).on('input', function() {
      $(this).height(0).height(this.scrollHeight - offset - parseInt($(this).css('padding-top')));
    });
  }
}

https://codepen.io/nanachi1/pen/rNNKrzQ

cela devrait fonctionner.

nanachi1
la source
0

@Georgiy Ivankin a fait une suggestion dans un commentaire, je l'ai utilisée avec succès :) -, mais avec de légers changements:

$('#note').on('keyup',function(e){
    var maxHeight = 200; 
    var f = document.getElementById('note'); 
    if (f.clientHeight < f.scrollHeight && f.scrollHeight < maxHeight ) 
        { f.style.height = f.scrollHeight + 'px'; }
    });      

Il arrête de s'étendre après avoir atteint une hauteur maximale de 200 px

davidman77
la source
0

Ancienne question mais vous pouvez faire quelque chose comme ceci:

html:

<textarea class="text-area" rows="1"></textarea>

jquery:

var baseH; // base scroll height

$('body')
    .one('focus.textarea', '.text-area', function(e) {
        baseH = this.scrollHeight;
    })
    .on('input.textarea', '.text-area', function(e) {
        if(baseH < this.scrollHeight) {
            $(this).height(0).height(this.scrollHeight);
        }
        else {
            $(this).height(0).height(baseH);
        }
    });

De cette façon, le redimensionnement automatique s'appliquera à n'importe quelle zone de texte avec la classe "zone de texte". Réduit également lorsque le texte est supprimé.

jsfiddle:

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

Rotaercz
la source
0

Essaye ça:

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

Solution jQuery simple:

$("textarea").keyup(function() {
    var scrollHeight = $(this).prop('scrollHeight') - parseInt($(this).css("paddingTop")) - parseInt($(this).css("paddingBottom"));

    if (scrollHeight > $(this).height()) {
        $(this).height(scrollHeight + "px");
    }
});

HTML:

<textarea rows="2" style="padding: 20px; overflow: hidden; resize: none;"></textarea>

Le débordement doit être masqué . Le redimensionnement est nul si vous ne souhaitez pas le redimensionner à la souris.

elano7
la source