CSS Textarea qui s'étend au fur et à mesure que vous tapez du texte

j'ai un Textarea où les utilisateurs peuvent entrer du texte. Par défaut, il a une hauteur de 17px. Cependant si les utilisateurs insèrent une grande quantité de texte, je veux que la zone de texte s'étende en conséquence. Y a-t-il un moyen de faire ça avec CSS ? Merci à l'avance!!

37
demandé sur Hussein 2011-02-10 09:57:04

13 réponses

cela ne peut pas être fait avec CSS seul. essayez le plugin jQuery d'autogrow. https://github.com/jaz303/jquery-grab-bag/blob/master/javascripts/jquery.autogrow-textarea.js

vous pouvez aussi voir la démo d'autogrow ici http://onehackoranother.com/projects/jquery/jquery-grab-bag/autogrow-textarea.html

Il est léger et facile à utiliser. Voici comment c'est fait. Définissez votre id textarea. Inclure le fichier jquery js avant </body>. Puis entre les balises de script, le problème de l'jquery commande $("#txtInput").autoGrow();

<body>
    <textarea id="txtInput"></textarea>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js" type="text/javascript"></script> 

<script>
    $("#txtInput").autogrow();
</script>
</body>
21
répondu Hussein 2017-01-07 13:22:32

ce plugin jQuery est vraiment génial: http://www.jacklmoore.com/autosize

j'en ai testé plusieurs et c'est de loin le plus joli. Donne également un exemple d'utilisation D'un effet de transition CSS qui est assez lisse.

20
répondu sirkitree 2012-11-01 13:20:20

Vous n'avez pas besoin d'un plugin pour cela. Cela fonctionne sur les textareas de n'importe quelle taille, hauteur ou taille de ligne et ne fonctionnera que lorsque le contenu dépasse la textarea. Tout d'abord définir le débordement sur votre cible textareas à caché et redimensionner à aucun, puis Ajouter la fonctionnalité suivante aux textareas que vous voulez autogrow. Non seulement il va augmenter la taille de la textarea que les types d'utilisateurs, il va également auto-rétrécir quand ils suppriment des trucs.

$('textarea').on('paste input', function () {
    if ($(this).outerHeight() > this.scrollHeight){
        $(this).height(1)
    }
    while ($(this).outerHeight() < this.scrollHeight + parseFloat($(this).css("borderTopWidth")) + parseFloat($(this).css("borderBottomWidth"))){
        $(this).height($(this).height() + 1)
    }
});

cela fonctionne en mesurant si la hauteur de défilement de la textarea est plus grand que la hauteur extérieure, qu'il ne sera que s'il y a plus de texte que la textarea peut contenir - et il tient compte de la taille de la bordure pour une plus grande précision. L'utilisation de coller et d'entrer signifie qu'il n'augmentera que lorsque l'utilisateur modifiera physiquement la valeur du textarea, par opposition à lorsqu'il appuie sur une touche. C'est mesquin, mais un textarea ne devrait pas pousser quand quelqu'un appuie sur une flèche ou quelque chose.

il pourrait être prudent d'ajouter une option Non JS qui ré-active débordement et redimensionnement pour ceux qui n'ont pas Javascript, sinon ils seront coincés avec une boîte minuscule.

12
répondu Woody Payne 2015-06-07 22:03:00

**notez que C'est très similaire à la réponse de Woody ci-dessus, mais je voulais l'étendre un peu et fournir un exemple de code d'exécution maintenant que Stack nous permet de les intégrer.

après avoir lu tout cela et essayé quelques plugins, j'ai découvert que rien de tout cela ne fonctionnait comme je l'avais espéré. J'ai fait ce qui suit - il y a un léger cliquetis au haut du champ pendant que vous faites défiler avant qu'il ne se dilate, mais cela fonctionne pour moi. J'ai utilisé jquery, mais peut être fait avec du javascript comme facilement en saisissant les valeurs de remplissage au lieu d'utiliser la hauteur intérieure:

  • définir une hauteur minimale sur la textarea dans css
  • Définir le débordement caché pour un défilement vertical (j'ai juste voulu s'étendre verticalement)
  • Réglez la hauteur à la hauteur de défilement moins de rembourrage sur chaque événement keyup si la hauteur de défilement était plus élevée que la hauteur + rembourrage (au centre).
  • si la hauteur de défilement n'était pas plus grande, j'ai re-réglé la hauteur à 1, et puis j'ai réglé la hauteur à faire défiler la hauteur moins de rembourrage (rétrécir la hauteur). Si vous ne réinitialisez pas à une plus petite hauteur initialement, la hauteur de défilement ne rétrécira pas.

$(function() {
  $('#myTextArea').on('keyup paste', function() {
    var $el = $(this),
        offset = $el.innerHeight() - $el.height();

    if ($el.innerHeight < this.scrollHeight) {
      //Grow the field if scroll height is smaller
      $el.height(this.scrollHeight - offset);
    } else {
      //Shrink the field and then re-set it to the scroll height in case it needs to shrink
      $el.height(1);
      $el.height(this.scrollHeight - offset);
    }
  });
});
#myTextArea {
  width: 250px;
  min-height: 35px;
  overflow-y: hidden;
}
<script src="https://code.jquery.com/jquery-2.2.3.min.js"></script>
<textarea id="myTextArea" placeholder="Hit enter a few times, it should expand"></textarea>
11
répondu Stephen Tremaine 2016-09-18 03:55:48

je sais que c'est un peu en retard, mais je dois dire qu'il y a un moyen d'utiliser <div>contenteditable attribut pour simuler le comportement désiré.

.textareaElement {
  width: 300px;
  min-height: 17px;
  border: 1px solid #ccc;
  max-height: 150px;
  overflow-x: hidden;
  overflow-y: auto;
}
<div class="textareaElement" contenteditable></div>

il suffit de définir votre hauteur min et max, avec des valeurs de débordement appropriées, et vous avez CSS pur expansion textbox entièrement fonctionnelle, qui est également bien pris en charge.

enter image description here

8
répondu Moo 2017-03-24 17:11:12

Utilisez JavaScript pour cela.

ce script vérifie la longueur de la zone de texte après chaque frappe (copypasta de ici):

  <textarea name="x" onKeyUp="SetNewSize(this);" cols="5" rows="4"></textarea>
    <script language="javascript">
    function SetNewSize(textarea){
      if (textarea.value.length > 5){
        textarea.cols = 50;
        textarea.rows = 50;
      }  else{
         textarea.cols = 10;
         textarea.rows = 15;
      }
    }
  </script>
4
répondu Nikita Barsukov 2011-02-10 07:04:32

Expansion textarea que vous tapez

tapez quelque chose dans textarea pour voir l'effet

<script>    
function increseRows(selector)
{
    $(selector).attr("rows", $(selector).val().split("\n").length+1||2);
}
</script>

expanding textarea as you type

1
répondu Prem Kumar Maurya 2014-04-07 15:44:13

j'utilise la suite (avec jQuery, bien sûr):

$(function () {
    'use strict';
    $("textarea").on('change keyup paste input', function () {
        $(this).attr("rows", Math.max($(this).val().split("\n").length || 1, $(this).attr("rows") || 1));
        $(this).css("width", $(this).css("width"));
    }).trigger('change');
});

Notez qu'il répond à divers événements, seulement augmente le nombre de lignes (c'est à dire ne pas diminuer), déclenche un changement initial (par exemple, pour redimensionner lors de la navigation de retour à une forme avec beaucoup de lignes)

1
répondu DigitalDan 2015-06-11 11:33:32

cela semble être beaucoup plus efficace et gère max-Hauteur

$(ctrl).on('paste input', function () {
    var dyLineHeight, dyMax, dyHeight;        
    if ($(this).outerHeight() > this.scrollHeight)
        $(this).height($(this).outerHeight() - parseFloat($(this).css("borderBottomWidth")) - parseFloat($(this).css("borderTopWidth")));
    dyLineHeight = Math.max(3, parseInt($(this).css("line-height")));
    dyMax = parseInt($(this).css("max-height"));
    while ($(this).outerHeight() < this.scrollHeight + parseFloat($(this).css("borderTopWidth")) + parseFloat($(this).css("borderBottomWidth")))
        {
        dyHeight = $(this).height();
        if (dyHeight >= dyMax)
            break;
        $(this).height(dyHeight + dyLineHeight)
        }
});
1
répondu Glenn Kreisel 2017-02-12 17:09:22

je cherchais une solution js pure (pas de jquery dans les projets) et j'ai fini par écrire ma propre solution. Il est très rapide, Pas de problèmes de compatibilité et ne nécessite pas de libs supplémentaires.

un détail à prendre en compte est que vous devez dimensionner la boîte avant que le nouveau caractère apparaisse, mais dimensionner la boîte après que le caractère disparaît (après avoir frappé le backspace ou supprimer)

function updateSize(e) {
  let text = e.target.value + String.fromCharCode(event.keyCode);
  e.target.rows = text.split(/\r\n|\r|\n/).length;
}

function keyDownUpdateSize(e) {
  if (event.keyCode != 8 && event.keyCode != 46)
    updateSize(e);
}

function keyUpUpdateSize(e) {
  if (event.keyCode == 8 || event.keyCode == 46)
    updateSize(e);
}

    
  
document.querySelector(selector_to_your_textarea).addEventListener("keydown", keyDownUpdateSize);
document.querySelector(selector_to_your_textarea).addEventListener("keyup", keyUpUpdateSize);
1
répondu Marek Kirejczyk 2017-04-26 06:45:16

Utilisez Javascript. textarea se comporte comme une textarea, et vous voulez changer cela (vous voulez qu'il se comporte comme une div), donc vous devez pirater le comportement que vous voulez.

Voici une solution que j'ai trouvée il y a quelques mois mais que je n'ai pas pu retrouver. Il peut avoir ma propre saveur ajoutée dans:

Syntaxe:

<div>
  <textarea class='my-textarea' />
  <div className='my-textarea autogrow' style="display: 'none';" />
</div>

Style:

.my-textarea {
  border: 1px solid #bbb;
  font-family: Helvetica;
  font-size: 15px;
  overflow: hidden;
  padding: 5px;
  resize: none;
}

// Needs same styles as the textarea except overflow.
.autogrow {
  overflow: auto !important;
}

Obtenir cet écouteur d'événement sur le textarea change événement:

function growTextarea(e) {
  const { value } = e.target
  const textarea = e.target
  const { grower } = this

  grower.style.display = 'block'
  grower.innerHTML = value.length ? value : 'x'
  textarea.style.height = grower.offsetHeight + 'px'
  grower.style.display = 'none'
}

Comment fait-il travail? Fondamentalement, l'expansion d'un div est ce que vous voulez que l'expansion du textarea se comporte comme. Donc, vous faites une div avec tous les mêmes styles que la textarea et mettre la valeur de la textarea dans la div. Ensuite, vous obtenez la hauteur de la div et réglez la hauteur de la textarea à cela.

en utilisant display none et block, le div apparaît et disparaît de sorte que vous pouvez mesurer sa hauteur. Vous ne le verrez jamais dans le navigateur.

Espérons que cela fonctionne pour vous!

P. M. j'utilise Réagir, donc j'ai dû changer ma solution pour être cadre agnostique. Il peut donc y avoir des bugs ou des erreurs de syntaxe. Par exemple: vous pourriez avoir à interroger le document pour trouver le cultivateur div.

0
répondu A.Williams 2017-05-21 18:13:23

si vous utilisez Angular2 / 4 Il y a un grand ici qui fonctionne.

voir la liste des problèmes pour quand vous chargez des données dynamiquement dans le textarea pour une solution de contournement. En dehors de cette question, il fonctionne très bien avec les formulaires de réactivation et les formulaires de modèle.

Pour la référence, c'est la directive de code:

import { Input, AfterViewInit, ElementRef, HostListener, Directive} from '@angular/core';

@Directive({
    selector: 'textarea[autosize]'
})

export class Autosize implements AfterViewInit {

    private el: HTMLElement;
    private _minHeight: string;
    private _maxHeight: string;
    private _lastHeight: number;
    private _clientWidth: number;

    @Input('minHeight')
    get minHeight() { 
      return this._minHeight;
    }
    set minHeight(val: string) {
      this._minHeight = val;
      this.updateMinHeight();
    }

    @Input('maxHeight')
    get maxHeight() {
      return this._maxHeight; 
    }
    set maxHeight(val: string) {
      this._maxHeight = val;
      this.updateMaxHeight();
    }

 @HostListener('window:resize', ['$event.target'])
    onResize(textArea: HTMLTextAreaElement) {
      //Only apply adjustment if element width had changed.
      if (this.el.clientWidth === this._clientWidth) return;
      this._clientWidth = this.element.nativeElement.clientWidth;
      this.adjust();
    }

 @HostListener('input',['$event.target'])
  onInput(textArea: HTMLTextAreaElement): void {
    this.adjust();  
  }

  constructor(public element: ElementRef){
    this.el = element.nativeElement;
    this._clientWidth = this.el.clientWidth;
  }

  ngAfterViewInit(): void{
    // set element resize allowed manually by user
    const style = window.getComputedStyle(this.el, null);
    if (style.resize === 'both') {
            this.el.style.resize = 'horizontal';
        }
    else if (style.resize === 'vertical') {
            this.el.style.resize = 'none';
    }
    // run first adjust
    this.adjust();
  }

  adjust(): void{
    // perform height adjustments after input changes, if height is different
    if (this.el.style.height == this.element.nativeElement.scrollHeight + "px") return;
    this.el.style.overflowX = 'hidden';
    this.el.style.height = 'auto';
    this.el.style.height = this.el.scrollHeight + "px";
  }

  updateMinHeight(): void{
    // Set textarea min height if input defined
    this.el.style.minHeight = this._minHeight + 'px';
  }

  updateMaxHeight(): void{
    // Set textarea max height if input defined
    this.el.style.maxHeight = this._maxHeight + 'px';
  }

}
0
répondu rmcsharry 2017-10-12 19:21:36

vieille question mais vous pourriez 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 quel textarea avec la classe "text-area". Réduit également lorsque le texte est supprimé.

jsfiddle:

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

0
répondu rotaercz 2017-11-10 23:31:30