Erstellen eines Textbereichs mit automatischer Größenänderung


366

Es gab einen anderen Thread darüber , den ich ausprobiert habe. Es gibt jedoch ein Problem: Das textareawird nicht kleiner, wenn Sie den Inhalt löschen. Ich kann keine Möglichkeit finden, es auf die richtige Größe zu verkleinern - der clientHeightWert wird als volle Größe des zurückgegeben textarea, nicht als Inhalt.

Der Code von dieser Seite ist unten:

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

Die akzeptierte Antwort für den von Ihnen verlinkten Thread funktioniert für mich. Durch Hinzufügen von Zeilenumbrüchen wird der Textbereich erweitert und durch Entfernen wird der Textbereich verkleinert. Welchen Browser verwenden Sie?
EndangeredMassa

3
Meine Funktion macht Fehler. Es ist unbedingt erforderlich, am Zeilenende eine neue Zeile einzugeben. Dies ist eine bessere Lösung. james.padolsey.com/javascript/jquery-plugin-autoresize

Sie können mein Plugin dafür versuchen: github.com/AndrewDryga/jQuery.Textarea.Autoresize
Andrew Dryga


Ich habe ein Paket dafür erstellt, wenn Sie reagieren verwenden: npmjs.com/package/react-fluid-textarea
Martin Dawson

Antworten:


230

Dies funktioniert bei mir (Firefox 3.6 / 4.0 und 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>

Wenn Sie es auf jsfiddle ausprobieren möchten, beginnt es mit einer einzelnen Zeile und vergrößert nur die genau erforderliche Menge. Es ist in Ordnung für eine einzelne textarea, aber ich wollte etwas schreiben, wo ich viele, viele solcher textareas haben würde (ungefähr so ​​viel, wie man normalerweise Zeilen in einem großen Textdokument haben würde). In diesem Fall ist es sehr langsam. (In Firefox ist es wahnsinnig langsam.) Ich hätte wirklich gerne einen Ansatz, der reines CSS verwendet. Dies wäre mit möglich contenteditable, aber ich möchte, dass es nur Klartext ist.


13
Es tut! Hat eine jsfiddle für dich gemacht: jsfiddle.net/CbqFv Es funktioniert jetzt in Chrome, Firefox und IE8 - obwohl es in IE8 ein wenig unangenehm ist. Wenn Sie die Anzahl der Zeilen erhöhen oder verringern, flippt es ein wenig aus. Wie Sie vielleicht im Autoresize-Plugin für jQuery gesehen haben, umgehen sie dies, indem sie den Textbereich klonen, seine Höhe auf Auto anstelle des Originals setzen und dann damit die Bildlaufhöhe für das Original festlegen. Ich habe das in dieser aktualisierten Geige getan : jsfiddle.net/CbqFv/2 Es löst das IE-Problem, aber Firefox funktioniert nicht mehr.
Chris Moschini

3
@HelenNeely: Dann benutze keine ID. Verwenden Sie beispielsweise eine Klasse und tun Sie, was init für alle Elemente dieser Klasse tut. Das sollte eine Anfängeraufgabe sein.
Panzi

3
@ DenilsonSá Wenn man nur davon ausgehen könnte, dass nur moderne Browser verwendet werden, wäre das Web ein besserer Ort.
Panzi

2
Dies funktioniert nicht gut, wenn in IE11 eine Bildlaufleiste enthalten ist. Wenn Sie diese Geige jsfiddle.net/CbqFv verwenden und Zeilen eingeben, bis Sie eine Bildlaufleiste haben, wird sie angezeigt . Irgendwelche Ideen?
Kaljak

6
Dies bricht vollständig ab, wenn sich der Textbereich in der Nähe des unteren Seitenendes befindet - aufgrund dessen springt alles vor und zurück style.height='auto'. Ich vermute, die Lösung besteht darin, ein verstecktes Geschwister hinzuzufügen, das nur zur Messung verwendet wird.
rr-

372

EINE KOMPLETTE NOCH EINFACHE LÖSUNG

Aktualisiert 14.05.2020 (Verbesserte Browserunterstützung für Handys und Tablets)

Der folgende Code funktioniert:

  • Bei Tastatureingabe.
  • Mit eingefügtem Text (Rechtsklick & Strg + V).
  • Mit ausgeschnittenem Text (Rechtsklick & Strg + x).
  • Mit vorinstalliertem Text.
  • Mit der gesamten Website aller Textbereiche (mehrzeilige Textfelder) .
  • Mit Firefox (v31-67 getestet).
  • Mit Chrome (v37-74 getestet).
  • Mit IE (v9-v11 getestet).
  • Mit Edge (v14-v18 getestet).
  • Mit IOS Safari .
  • Mit Android Browser .
  • Mit JavaScript strengen Modus .
  • Ist w3c validiert.
  • Und ist rationalisiert und effizient.

OPTION 1 (Mit jQuery)

Diese Option erfordert jQuery und wurde getestet und funktioniert mit 1.7.2 - 3.3.1

Einfach (Fügen Sie diesen Abfragecode zu Ihrer Master-Skriptdatei hinzu und vergessen Sie ihn.)

$('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 (reines JavaScript)

Einfach (Fügen Sie dieses JavaScript zu Ihrer Master-Skriptdatei hinzu und vergessen Sie es.)

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 (jQuery-Erweiterung)

Nützlich, wenn Sie die Textbereiche, deren Größe automatisch angepasst werden soll, weiter verketten möchten.

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

Rufen Sie mit auf $('textarea').autoHeight()


AKTUALISIERUNG VON TEXTAREA ÜBER JAVASCRIPT

Wenn Sie Inhalte über JavaScript in einen Textbereich einfügen, fügen Sie den folgenden Code hinzu, um die Funktion in Option 1 aufzurufen.

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

PRESET TEXTAREA HÖHE

Um die Anfangshöhe des Textbereichs festzulegen, müssen Sie eine zusätzliche Bedingung hinzufügen:

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>


12
Dies ist eine großartige Lösung. Es wäre etwas verständlicher, wenn der Methodenname und der Parametername so aktualisiert würden, dass sie wahre Namen anstelle einzelner Buchstaben sind.
Chris Marisic

5
@Obsidian Danke! Ich habe gerade herausgefunden, warum ich immer eine 0 bekomme - ich habe den Textbereich in ein Bootstrap-Modal eingefügt! Da das Modal zuerst ausgeblendet ist, hat das Textfeld
darin

7
@Obsidian Fantastisch !! (Option 3). Das this.style.height = 'auto';ist die magische Verhaltensbehebung. Ich war so frustriert, warum sich die scrollHeight so komisch verhielt. Die Höhe auf Auto und dann die Anpassung an die scrollHeight im selben Renderzyklus beeindruckt mich immer noch davon, wie dieses Problem behoben wird, obwohl nur die zweite Höhe technisch gezeichnet werden sollte.
Bit-less

2
Ich habe heute Option 3 in Chrome ausprobiert und musste einige Änderungen vornehmen. 1) Die Größe wird nicht immer korrekt geändert, wenn Sie einen "Höhe" - oder "Alle" -Übergang im Textbereich haben. Ich würde empfehlen, keine Übergänge zu verwenden, die sich auf die Höhe auswirken. 2) Die scrollHeight hat mindestens zwei Zeilen mit der Höhe zurückgegeben (möglicherweise, weil dies die Standardeinstellung für Textbereiche in Chrome ist), aber wenn Sie this.style.height = 'auto' ändern; to this.style.height = '0px'; und fügen Sie eine Mindesthöhe hinzu, um zu verhindern, dass der Anfangszustand tatsächlich auf 0 geht. scrollHeight gibt gegebenenfalls eine Zeilenhöhe korrekt zurück.
ZorroDeLaArena

3
@Obsidian Können Sie erklären, wie this.style.height = 'auto';das Verhalten von scrollHeight behoben wird? Es ist nur Magie.
Sidney

63

Die jQuery-Lösung passt das CSS an Ihre Anforderungen an

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

ODER Alternative für jQuery 1.7 + ...

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

Ich habe eine Geige mit dem absoluten Minimum an Styling als Ausgangspunkt für Ihre Experimente erstellt ... http://jsfiddle.net/53eAy/951/


5
Dies ist gut, aber ich würde overflow-y: hidden;dem CSS hinzufügen, um zu verhindern, dass die Bildlaufleiste kurz blinkt, wenn die Größe geändert wird.
Brettjonesdev

Nicht ganz sicher, aber ohne sie wächst der Textbereich um zu viel. Ich denke, das hängt damit zusammen, wie die Elemente scrollHeight berechnet werden.
Chim

1
Verwenden Sie mehrere Ereignisse, um Arbeit für eine breite Wahrheit des Szenarios zu machen $('textarea.auto-resize').on('change cut paste drop keyup', function(){...})
Raxith

1
Springt wie verrückt in Chrome 40 Win 8.1 auf Texten herum, die länger als das Ansichtsfenster sind. Macht es ziemlich unbrauchbar.
Tobibeer

1
Wenn Sie die Eingabetaste (Zeilenumbruch) gedrückt halten, wird ein Bildlauf durchgeführt. Die Größe wird erst angepasst, wenn die Taste losgelassen wird.
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>

Getestet in Firefox 14 und Chrom 18. Die Nummern 24 und 12 sind willkürlich. Testen Sie, was am besten zu Ihnen passt.

Sie könnten auf die Stil- und Skript-Tags verzichten, aber es wird imho etwas chaotisch (dies ist HTML + JS im alten Stil und wird nicht empfohlen).

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

Bearbeiten: modernisierter Code. Das onkeyup-Attribut wurde in addEventListener geändert.
Bearbeiten: Keydown funktioniert besser als Keyup
Bearbeiten: Deklarieren der Funktion vor Verwendung von
Bearbeiten: Eingabe funktioniert besser als Keydown (thnx @ WASD42 & @ MA-Maddin)

jsfiddle


3
Dieser hat einige Nachteile: 1) Die Größe des Textbereichs wird nicht geändert, dann fügt der Benutzer etwas nur mit den Maustasten ein. 2) Wenn der Benutzer etwas über die Tastatur einfügt (Strg + V), wird die Größe des Textbereichs nur geändert, wenn er Strg loslässt. Wenn der Benutzer mehrmals Strg + V drückt, wächst der Textbereich erst nach dem letzten. Sie sollten dieselbe Funktion auch zum Einfügen, Ausschneiden, Ändern und Löschen von Ereignissen hinzufügen.
WASD42

Verwenden Sie inputstattdessen einfach das Ereignis. Siehe stackoverflow.com/a/14029861/1951524
Martin Schneider

Verbesserte Version mit mehrfacher textareaUnterstützung als document.querySelectorAll('textarea').forEach(function(te){ te.addEventListener("input", function() { this.style.height='24px'; this.style.height=this.scrollHeight+12+'px'; }); });
Meisner

1
@ Meisner Es ist kürzer, aber ich würde nicht sagen, dass es "verbessert" ist. Mit einer anonymen Funktion removeEventListenerkönnen Sie Ihre Ereignis-Listener nicht aufrufen und bereinigen. Dies ist besonders wichtig, wenn Sie überall in einer forEach-Schleife Ereignis-Listener erstellen. Außerdem ist aus meiner Sicht die Lesbarkeit weitaus wichtiger als die Prägnanz.
GijsjanB

box-sizing: border-box;Stellen Sie für andere und zukünftige Personen sicher, dass die Eigenschaft festgelegt ist. Andernfalls wird der Textbereich für jedes onInput-Ereignis um 4 Pixel erweitert. Ich verbrachte ungefähr 3 Stunden, bis ich herausfand, dass dies das Problem war.
Am

24

Die beste Lösung (funktioniert und ist kurz) für mich ist:

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

Es funktioniert wie ein Zauber, ohne mit Paste zu blinken (auch mit der Maus), zu schneiden, einzutreten und auf die richtige Größe zu schrumpfen.

Bitte werfen Sie einen Blick auf jsFiddle .


Umwerfend!!! One Line Deal! dumme Frage Wie kann ich eine Animation hinzufügen, wenn die Größe geändert wird? wie das Textfeld sorta sanft Größe ändern, anstatt den Sprung zur Größe?
user2513846

1
@ user2513846 Sieht so aus, als wäre dies durch das Design der mehrzeiligen Bearbeitung nicht möglich. Ich habe ein Beispiel für die Größe eines animierten Textbereichs erstellt: jsfiddle.net/yk2g333e Wie Sie wissen, bewegt sich der Textcursor an der und der Zeile oder des Carets nach unten. Wenn in diesem Moment keine Pause vorliegt, gibt es nichts zu animieren. Aber das Anhalten wird für den Benutzer zu ärgerlich sein.
Vatavale

1
@ user2513846 Mit einer weiteren leeren Zeile am Ende des Textbereichs ist es jedoch möglich, eine reibungslose Animation zu haben: jsfiddle.net/p23erdfr
vatavale

16

Sie verwenden den höheren Wert der aktuellen clientHeight und des Inhalts scrollHeight. Wenn Sie die scrollHeight durch Entfernen von Inhalten verkleinern, kann der berechnete Bereich nicht kleiner werden, da die zuvor durch style.height festgelegte clientHeight sie offen hält. Sie können stattdessen ein Maximum () von scrollHeight und einen minimalen Höhenwert verwenden, den Sie aus textarea.rows vordefiniert oder berechnet haben.

Im Allgemeinen sollten Sie sich bei Formularsteuerelementen wahrscheinlich nicht wirklich auf scrollHeight verlassen. Abgesehen davon, dass scrollHeight traditionell weniger weit verbreitet ist als einige der anderen IE-Erweiterungen, sagt HTML / CSS nichts darüber aus, wie Formularsteuerelemente intern implementiert werden, und Sie können nicht garantieren, dass scrollHeight von Bedeutung ist. (Traditionell haben einige Browser Betriebssystem-Widgets für die Aufgabe verwendet, wodurch eine CSS- und DOM-Interaktion auf ihren Interna unmöglich wird.) Überprüfen Sie zumindest die Existenz von scrollHeight / clientHeight, bevor Sie versuchen, den Effekt zu aktivieren.

Ein anderer möglicher alternativer Ansatz, um das Problem zu vermeiden, wenn es wichtig ist, dass es breiter funktioniert, besteht darin, ein verstecktes Div zu verwenden, das auf die gleiche Breite wie der Textbereich dimensioniert und in derselben Schriftart festgelegt ist. Bei der Eingabe kopieren Sie den Text aus dem Textbereich in einen Textknoten in verstecktem div (denken Sie daran, '\ n' durch einen Zeilenumbruch zu ersetzen und '<' / '&' ordnungsgemäß zu maskieren, wenn Sie innerHTML verwenden). Wenn Sie dann einfach den Versatz des Div messen, erhalten Sie die Höhe, die Sie benötigen.


1
Mit welchen Browsern sollen Probleme bei scrollHeightTextbereichen auftreten? Funktioniert gut mit aktuellen Versionen von IE, Firefox und Opera ...
Christoph

1
Der einzige, den ich zur Hand haben muss, ist Konqueror, der clientHeight als scrollHeight zurückgibt. Dies ist ein Verhalten, das Sie erwarten können, wenn der Browser das CSS-Box-Modell nicht auf die Interna von Widgets anwendet, was sie nicht immer getan haben und der Standard dies nicht vorschreibt.
Bobince

14

Wenn Sie IE8 nicht unterstützen müssen, können Sie das inputEreignis verwenden:

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

Jetzt müssen Sie nur noch CSS hinzufügen und fertig:

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

Verwendungszweck:

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

Weitere Informationen zur Funktionsweise finden Sie in meinem Blogbeitrag .


1
Schöne Lösung, braucht aber wenig Fix. Wenn der Inhalt des Textbereichs geladen wird, z. Aus der Datenbank bleiben die Textbereiche klein. Sie müssen ein inputEreignis während der Initialisierung in jedem Zyklus auslösen .
Ajax

11

Automatische skalierung

https://github.com/jackmoore/autosize

Just Works, Standalone, ist beliebt (3.0k + GitHub-Stars ab Oktober 2018), verfügbar auf CDNJs ) und leicht (~ 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>

Übrigens, wenn Sie den ACE-Editor verwenden, verwenden Sie maxLines: Infinity: Passen Sie die Höhe automatisch an den Inhalt im Ace Cloud 9-Editor an


2
Version 2 wurde im Februar 2015 veröffentlicht. Sie ist einfacher geworden und hängt nicht mehr von jQuery ab
knusprig

Entschuldigung, es funktioniert. Vielleicht war ich in einem anderen Browser.
Also

@ ToniMichelCaubet ah, OK vielleicht CDN Problem dann. Lass mich das überprüfen.
Ciro Santilli 法轮功 冠状 病 六四 事件 2

Das autosizePlugin erlaubt keine manuelle Größenänderung mithilfe des Größenänderungssymbols im Textbereich.
j4v1

7

Ich habe von hier aus einen Einzeiler gefunden .

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

6

Hat jemand als inhaltsbearbeitbar angesehen? Kein Herumspielen mit dem Scrollen, und das einzige JS, das ich daran mag, ist, wenn Sie vorhaben, die Daten bei Unschärfe zu speichern ... und anscheinend ist es mit allen gängigen Browsern kompatibel: http://caniuse.com/#feat = inhaltsbearbeitbar

Gestalte es einfach so, dass es wie ein Textfeld aussieht, und es wird automatisch angepasst ... Machen Sie seine minimale Höhe zur bevorzugten Texthöhe und haben Sie es.

Das Coole an diesem Ansatz ist, dass Sie einige Browser speichern und mit Tags versehen können.

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>

Chrome fügt bei ENTER <div> -Elemente hinzu.
Sbaechler

contenteditableist gut, aber wenn Sie Klartext wollen, braucht es eine Reihe von Optionen wie -webkit-user-modify: read-write-plaintext-onlyund white-space: pre-wrap.
mik01aj

@_sbaechler: Die <div> s werden bei der Verwendung weggelassen [dom-element].innerText. @WebmasterG IMHO wäre es schön, jquery (aus Gründen der Transparenz) wegzulassen und das Beispiel auf dieser Seite über ein ausführbares Code-Snippet anstelle von jsfiddle aufzunehmen.
Adabru

4

Ich habe den folgenden Code für mehrere Textbereiche verwendet. Funktioniert problemlos in Chrome 12, Firefox 5 und IE 9, auch wenn in den Textbereichen Aktionen zum Löschen, Ausschneiden und Einfügen ausgeführt werden.

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

4

Es gibt einen etwas anderen Ansatz.

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

Die Idee ist, den Text von textareain das zu kopieren preund CSS sicherstellen zu lassen, dass sie dieselbe Größe haben.

Der Vorteil besteht darin, dass Frameworks einfache Tools zum Verschieben von Text bieten, ohne Ereignisse zu berühren. In AngularJS würden Sie nämlich ein ng-model="foo" ng-trim="false"zum textareaund ng-bind="foo + '\n'"zum hinzufügen pre. Sehen Sie eine Geige .

Stellen Sie einfach sicher, dass predie Schriftgröße dieselbe ist wie die textarea.


1
" Stellen Sie einfach sicher, dass predie gleiche Schriftgröße wie dietextarea " - Sie benötigen die gleiche line-heightund die gleiche Menge von paddingund / oder borderauch. Dies ist die beste Lösung für Angular.
Jamie Barker

4

Das Folgende funktioniert zum Ausschneiden, Einfügen usw., unabhängig davon, ob diese Aktionen über die Maus, eine Tastenkombination oder die Auswahl einer Option in einer Menüleiste ausgeführt werden. Mehrere Antworten verfolgen einen ähnlichen Ansatz, berücksichtigen jedoch nicht die Box- Größe, weshalb sie den Stil falsch anwenden overflow: hidden .

Ich mache folgendes, was auch gut mit max-heightund rowsfür minimale und maximale Höhe funktioniert .

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>

Der Vollständigkeit halber sollten Sie die adjustFunktion unter folgenden Umständen aufrufen :

  1. Fenstergröße ändern Ereignisse, wenn die Breite der textarea Fenster mit der Fenstergröße ändert, oder andere Ereignisse, die die Breite des Textbereichs ändern
  2. Wenn sich das Stilattribut des textarea' displayändert, z. B. wenn es von gehtnone (versteckt) nach wechseltblock
  3. Wenn der Wert von textareaprogrammgesteuert geändert wird

Beachten Sie, dass das Verwenden window.getComputedStyleoder Abrufen currentStyleetwas rechenintensiv sein kann. Daher möchten Sie möglicherweise stattdessen das Ergebnis zwischenspeichern.

Funktioniert für IE6, also hoffe ich wirklich, dass die Unterstützung gut genug ist.


4

Als anderen Ansatz können Sie einen verwenden, <span>der seine Größe automatisch anpasst. Sie müssen es bearbeitbar machen, indem Sie die contenteditable="true"Eigenschaft hinzufügen, und fertig:

div {
  width: 200px;
}

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

Das einzige Problem bei diesem Ansatz ist, dass Sie, wenn Sie den Wert als Teil des Formulars senden möchten, dies selbst in JavaScript tun müssen. Dies ist relativ einfach. Sie können beispielsweise ein ausgeblendetes Feld hinzufügen und im onsubmitFalle des Formulars den Wert von spandem ausgeblendeten Feld zuweisen, das dann automatisch mit dem Formular gesendet wird.


Es gibt bereits eine Antwort mit contenteditable
adabru

@adabru Ja, aber die beiden Antworten sind nicht gleich. Toyota macht rote Autos und Ford macht auch rote Autos, aber sie sind anders, nicht wahr? Wenn Ihnen die andere Antwort besser gefällt, dann machen Sie mit. Aber es gibt diejenigen, die meine Antwort mehr schätzen und mitmachen. Verschiedene Optionen zu haben ist gut.
Racil Hilan

3

Ein bisschen Korrekturen. Funktioniert perfekt in 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;
  });

funktioniert, solange Ihre Leitungen nicht überlaufen - dann passen sie nicht.
Tomáš Kafka

funktioniert
sofort

2

Ich kenne eine kurze und korrekte Methode, um dies mit jquery zu implementieren. Kein zusätzliches verstecktes div erforderlich und funktioniert in den meisten Browsern

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

jQuery's .live()ist veraltet. api.jquery.com/live Sie möchten im Allgemeinen .on()stattdessen verwenden.
Luke

2

Ich weiß nicht, ob jemand dies erwähnt, aber in einigen Fällen ist es möglich, die Höhe mit dem Zeilenattribut zu ändern

textarea.setAttribute('rows',breaks);

Demo


1
Das funktioniert nur, wenn Sie haben white-space: nowrap;. Wenn eine Zeile ohne Zeilenumbruch in eine andere Zeile umgebrochen wird, wird der Textbereich nicht mehr richtig angepasst.
Yeti

2

Hier ist eine eckige Direktive für Panzis Antwort.

 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>

Sie sollten lieber $ timeout als setTimout verwenden - dies stellt sicher, dass das Modell initialisiert wird (keine Angabe von Millisekunden erforderlich - es wird nach dem Angular Digest-Zyklus ausgeführt). Auch Element = Element [0]; ist eine sehr schlechte Praxis ... Wie auch immer, die Lösung ist nicht gut für mich, da der Textbereich einzeilig sein muss, bis mehr Text vorhanden ist.
Karol Websky

2

Sie können JQuery verwenden, um das zu erweitern textarea während der Eingabe :

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


Sauberste Lösung. aber wie wir aufhören sollten, jQuery zu verwenden: textarea.addEventListener ('keyup', () => {textarea.style.height = 0; textarea.style.height = ${textarea.scrollHeight}px;});
Toni Michel Caubet

2

Diejenigen, die dasselbe in neuen Versionen von Angular erreichen wollen.

Schnapp dir textArea elementRef.

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

Ich füge auch einen weiteren Anwendungsfall hinzu, der für einige Benutzer, die den Thread lesen, nützlich sein kann. Wenn der Benutzer die Höhe des Textbereichs auf eine bestimmte Höhe erhöhen und dann darauf setzen möchte, overflow:scrollkann die oben beschriebene Methode erweitert werden, um den genannten Anwendungsfall zu erreichen.

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

1

Einige der Antworten hier berücksichtigen nicht das Auffüllen.

Vorausgesetzt, Sie haben eine maximale Höhe, die Sie nicht überschreiten möchten, hat dies für mich funktioniert:

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

1

Ein noch einfacherer und sauberer Ansatz ist folgender:

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

// und das 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
}

Alles, was benötigt wird, ist das Hinzufügen der .auto-heightKlasse zu einer beliebigentextarea Sie abzielen möchten.

Getestet in FF, Chrome und Safari. Lassen Sie mich wissen, wenn dies aus irgendeinem Grund bei Ihnen nicht funktioniert. Aber dies ist der sauberste und einfachste Weg, auf dem ich festgestellt habe, dass dies funktioniert. Und es funktioniert super! : D.


Haben Sie versucht, Text nach der Bearbeitung zu entfernen? Ist der Textbereich zusammengebrochen?
18.

1

Dieser Code funktioniert zum Einfügen und wählen Sie auch Löschen.

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>

Hier ist die JSFiddle


1

Ich empfehle die Javascript-Bibliothek von http://javierjulio.github.io/textarea-autosize .

Fügen Sie pro Kommentar einen Beispielcodeblock zur Verwendung des Plugins hinzu:

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

Erforderliches Mindest-CSS:

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

1

MakeTextAreaResisable, das qQuery verwendet

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


1

Meine Implementierung ist sehr einfach. Zählen Sie die Anzahl der Zeilen in der Eingabe (und mindestens 2 Zeilen, um zu zeigen, dass es sich um einen Textbereich handelt):

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

Vollständiges Arbeitsbeispiel mit Stimulus: https://jsbin.com/kajosolini/1/edit?html,js,output

(und dies funktioniert zum Beispiel mit dem manuellen Größenänderungshandle des Browsers)


2
Dies funktioniert nur, wenn Sie die Zeile durch Drücken der Eingabetaste unterbrechen. Wenn Ihr Text länger als die Breite des Textbereichs ist, Sie jedoch nicht die Eingabetaste drücken, wird er nicht erweitert.
Nathalia Xavier

1

Akzeptierte Antwort funktioniert gut. Aber das ist viel Code für diese einfache Funktionalität. Der folgende Code reicht aus.

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

0

Folgendes habe ich getan, als ich MVC HTML Helper für TextArea verwendet habe. Ich hatte einige Textbereichselemente und musste sie anhand der Modell-ID unterscheiden.

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

und im Skript hinzugefügt dies:

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

Ich habe es auf IE10 und Firefox23 getestet


0

Sie können diesen Code verwenden:

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();
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.