Standardmäßig ändern <input>- und <textarea>-Elemente ihre Größe nicht basierend auf ihrem Inhalt. Tatsächlich gibt es keine einfache HTML- oder CSS-Methode, um dies zu erreichen. Ziemlich lustig, da dies ein sinnvoller Anwendungsfall zu sein scheint. Aber natürlich gibt es Wege, mein Freund. Es gibt immer Wege.
Ich dachte darüber nach, nachdem Remy Sharp kürzlich darüber gebloggt hat, im Kontext von Inline-<input>-Elementen.
Nicht-Input-Elemente dehnen sich natürlich aus
Es ist seltsam für mich, dass es keine Möglichkeit gibt, ein Eingabeelement dazu zu zwingen, dieses Verhalten nachzuahmen, aber leider.
Wir können jedes Element mit dem Attribut contenteditable editierbar und eingabeähnlich machen
<span
class="input"
role="textbox"
contenteditable>
99
</span>
Dieses <span> wird sich natürlich auf die Breite ausdehnen, die es für seinen Inhalt benötigt. Wenn es sich um ein <div> oder ein anderes Block-Element handeln würde, würde es sich auch vertikal nach Bedarf ausdehnen.
Aber sind Nicht-Input-Elemente zugänglich?
Ich bin mir nicht ganz sicher. Beachten Sie, dass ich role="textbox" auf das Element gesetzt habe. Das ist nur eine Best-Guess basierend auf einigen Dokumenten.
Selbst wenn das hilfreich ist...
- Was ist mit der Tatsache, dass Formulare mit der Enter-Taste abgeschickt werden können?
- Was ist mit der Idee, dass Formulardaten oft serialisiert und gesendet werden, während der Code, der das tut, wahrscheinlich nicht nach einem Span sucht?
- Wird es für einen Screenreader tatsächlich genauso gelesen wie ein Eingabefeld?
- Welche anderen Dinge¹ tun Eingabefelder natürlich, an die ich nicht denke?
So sehr ich von der Idee angetan bin, dass wir automatische Größenanpassung kostenlos vom Browser erhalten können, indem wir Nicht-Input-Elemente verwenden, so sehr mache ich mir auch ein wenig Sorgen über das (für mich) unbekannte Usability- und Zugänglichkeitsrisiko.
Größenanpassung tatsächlicher Eingabeelemente
Nehmen wir also an, wir bleiben bei <input> und <textarea>. Können wir sie größenveränderlich machen, obwohl das nicht besonders natürlich ist?
Eine Idee, die ich hatte, ist, die Eingabe in ein relatives Inline-Elternteil zu wickeln und es darin absolut zu positionieren. Dann könnten wir mit JavaScript den Wert der Eingabe mit einem versteckten Span innerhalb dieses Wrappers synchronisieren, wodurch die Breite nach Bedarf erhöht wird.
Für Textbereiche ist eine klassische Technik die Anzahl der Zeilenumbrüche zu zählen, diese zu verwenden, um die Höhe festzulegen, und sie dann mit der Zeilenhöhe zu multiplizieren. Das funktioniert gut für vorformatierte Texte, wie Code, aber überhaupt nicht für lange, absatzähnliche Inhalte.
Hier sind all diese Ideen kombiniert.
Weitere Ideen
Shaw hat eine kleine Einzeiler-JavaScript-Lösung, die *sehr clever* ist. Das JavaScript setzt ein data-*-Attribut auf das Element, das dem Wert des Eingabefeldes entspricht. Das Eingabefeld ist in einem CSS-Grid platziert, wobei dieses Grid ein Pseudo-Element ist, das dieses data-*-Attribut als Inhalt verwendet. Dieser Inhalt dehnt das Grid auf die entsprechende Größe basierend auf dem Eingabewert aus.
Eure Ideen
Ich weiß absolut, dass ihr anderen Web-Nerds das schon hunderttausendfach gelöst habt. Lasst sie uns in den Kommentaren sehen.
- Eric Bailey hat mir ein paar Gedanken aus dem Ärmel geschüttelt: (1) Es gibt keinen zugänglichen Namen. (2) Es wird wahrscheinlich nicht mit Sprachsteuerung funktionieren. (3) Es wird im Hochkontrastmodus ignoriert.
Dieser Einzeiler mit CSS-Grid von Shaw ist genial! Hat er irgendwelche Nachteile oder Nebenwirkungen? Ich schätze, das würden wir erst wissen, wenn es in einem echten Layout wäre, aber es scheint mir in Ordnung zu sein.
Nur zur Info, ich habe vor ungefähr 8 Jahren eine Lösung erstellt (wie 8 Jahre her (Chris, du hast sogar dazu kommentiert!)), die einen geklonten div-Element verwendet, von dem ich die Größe für den Textbereich 'ausleihe'. Ich habe sie kürzlich aktualisiert, um kein jQuery mehr zu verwenden und moderneres JS zu nutzen (obwohl sie immer noch etwas altes IE-Zeug enthält, das Sie entfernen können). CodePen hier.
Die Verwendung von ::before oder ::after könnte ein Problem sein. Abhängig von Ihrer Browser- & Screenreader-Kombination wird der generierte Inhalt laut vorgelesen. Mit einem separaten HTML-Element können Sie aria-hidden setzen, um dies zu verhindern, wie im ersten Beispiel.
Die SPAN-Methode ist sehr nützlich und ich benutze sie, aber es gibt ein Problem. Copy & Paste fügt einen Span in den Block ein. Ich werde mich nach der Bearbeitung per onkeydown oder etwas Ähnlichem umsehen, aber es ist seltsam, weil der Span nicht einfach in einen Editor eingefügt wird, nur der Span, der den Textbereich nachahmt. Wenn jemand eine Lösung hat, lasst es mich wissen.
Verwendete eine Methode, bei der
overflow-y: hidden;auf dem Textbereich gesetzt wird und dann ein Ereignishandler auf deminput-Ereignis wartet. Die Höhen-Stil wird dann mit dem scrollHeight-Wert aktualisiert.Vergessen Sie nicht, die Höhe beim Laden der Seite/Einfügen des DOMs festzulegen.
Ich verwende eine modifizierte Version, die ich aus verschiedenen Online-Quellen zusammengestellt habe, mit nur geringfügigen Anpassungen.
Es ist etwas unhandlich, weil ich es nicht so gestaltet habe, dass es dynamisch erstellte Elemente prüft, also habe ich ein "mousedown"-Ereignis hinzugefügt.
Außerdem ist dies die jQuery-Version zur Kürze.
Wenn jemand Verbesserungen hat, würde ich es gerne wissen. Ich mag Hacks überhaupt nicht, daher bin ich wirklich nicht geneigt, die Beispiele aus dem Artikel zu verwenden.
Vielleicht erfordert dies eine einfache Browserfunktion? Oder eine Erweiterung von CSS?
Ich fühlte mich verpflichtet, dafür einen Codepen zu erstellen. (Ich habe ihn ein wenig vom obigen Kommentar abgewandelt)
Das ist ziemlich gut, wenn auch nicht fehlerfrei. Das Beispiel "auf Klick/Fokus erweitern" wurde viel höher als nötig (zumindest auf meinem Chrome/Windows 10 Browser). Das Beispiel "beim Tippen erweitern" ist besser, obwohl es manchmal eine leere Zeile am Ende hat und manchmal nicht (scheint vom eingegebenen Text abzuhängen). Aber insgesamt gefällt mir Ihre Lösung besser als meine.
Meine Lösung bestand darin, ein verstecktes DIV mit der gleichen Breite, Rändern, Abständen, Polsterung, Schriftgröße, Zeilenhöhe usw. wie das TEXTBOX zu erstellen, den Inhalt aus dem TEXTBOX in das DIV zu duplizieren und dann die Höhe des DIV zu messen und diese Höhe auf das TEXTBOX anzuwenden.
Ihre Lösung hat den Vorteil, dass kein zusätzliches DIV benötigt wird.
Okay, die Verwendung von scrollHeight ist irgendwie genial. Ich werde dieses Konzept auf jeden Fall stehlen!
Okay, ich habe beschlossen, diese Methode in meinem Vue-Projekt zu verwenden. Ich setze auch dynamisch Overflow, um Scrollbar-Flashen zu verhindern, indem ich den berechneten Wert der maximalen Höhe des Textbereichs beobachte. Ein wichtiger Punkt hier ist, rows="1" zu setzen, was standardmäßig auf 2 gesetzt zu sein scheint, sodass Sie, wenn Sie alle Ihre Zeilen löschen, zu Ihrer Anfangshöhe zurückkehren können. Dies erfüllt mehr oder weniger alle Anforderungen, einschließlich der vollständigen Responsivität.
Siehe den Pen Auto Height Adjusting Textarea von Ian
(@iancwoodward) auf CodePen.
Gute Ideen hier, alle mit verschiedenen Vor- und Nachteilen. Ich denke, es ist immer am besten, den richtigen Ansatz für ein Projekt zu wählen, es gibt fast nie eine einzige Lösung für Probleme.
Wir haben native Textbereichsgrößenanpassung in einer ECMAScript-Klasse erstellt und letztes Jahr darüber für Colloq geschrieben. Ebenfalls relativ einfach und effektiv und mit einem modernen Ansatz.
https://github.com/LeaVerou/awesomplete
Vor ein paar Jahren hatte ich die Notwendigkeit, ein <DIV>, das für eine Popup-Nachricht verwendet wurde, erweitern zu lassen, wenn der Ausgabetext der Popup-Nachricht die Grenzen des Nachrichtenfeldes überschritt.
Ich konnte mich nicht erinnern, wie ich das gemacht hatte, also habe ich heute Morgen das Internet nach derselben Lösung durchsucht, als ich auf Ihren Beitrag gestoßen bin. Später fand ich meinen alten Code und passte ihn an meine heutigen Bedürfnisse an, aber dann erweiterte ich ihn und erstellte eine DEMO, die INPUT- und TEXTAREA-HTML-Elemente erweitert, wenn sich ihr Inhalt ausdehnt, die ich hier zurückposten könnte. Ich habe die DEMO in ein öffentliches GitHub-Repository hochgeladen.
Sie können die Demo hier finden
https://github.com/PaulSwarthout/Input-Expansion-Demo
Das Javascript befindet sich im <HEAD></HEAD>. Die gesamte Funktionalität befindet sich in der Funktion input_test() {…}.
Ich hoffe, das hilft jemandem.
Gibt es für die Lösung eine CSS-Lösung, bei der der eingefügte Text nicht gestylt wird? Dass er als reiner Text eingefügt wird?
Gibt es für die
<span>-Methode eine CSS-Lösung, bei der der eingefügte Text nicht gestylt wird? Dass er als reiner Text eingefügt wird?Hier ist meine Web-Komponenten-Version der cleveren data-* Lösung
Warum nicht einfach .scrollWidth verwenden?
Nur für Eingaben
<input type="text" size="1" oninput="this.setAttribute('size',this.value.length||=1)">Die Lösung von Shaw war großartig! Hat in meiner App sehr gut funktioniert. Danke!
In Microsoft Teams haben wir Textbereiche, die genau solche Features haben, die ich in Angular bauen muss, mit denselben Features.