Der sauberste Trick für automatisch wachsende Textbereiche

Avatar of Chris Coyier
Chris Coyier am

DigitalOcean bietet Cloud-Produkte für jede Phase Ihrer Reise. Starten Sie mit 200 $ kostenlosem Guthaben!

Anfang des Jahres habe ich etwas über automatisch wachsende Textbereiche und Eingabefelder geschrieben. Die Idee war, ein <textarea> mehr wie ein <div> zu gestalten, sodass es sich in der Höhe ausdehnt, so viel wie nötig, um den aktuellen Wert aufzunehmen. Es ist fast seltsam, dass es dafür keine einfache native Lösung gibt, oder? Rückblickend auf diesen Artikel waren keine meiner Ideen besonders gut. Aber Stephen Shaws Idee, auf die ich am Ende verwiesen habe, ist tatsächlich eine sehr gute Idee dafür, daher wollte ich dem etwas Aufmerksamkeit schenken und erklären, wie sie funktioniert, denn es scheint die endgültige Antwort darauf zu sein, wie diese Benutzererfahrung umgesetzt werden kann, bis wir etwas Natives und Besseres erhalten.

Hier ist die Demo, falls Sie nur ein funktionierendes Beispiel wünschen

Der Trick besteht darin, den Inhalt des <textarea> exakt in einem Element zu replizieren, das die Höhe automatisch erweitern und seine Größe anpassen kann.

Sie haben also ein <textarea>, das die Höhe nicht automatisch erweitern kann.

Stattdessen replizieren Sie das Aussehen, den Inhalt und die Position des Elements exakt in einem anderen Element. Sie verstecken die Replikation visuell (man kann genauso gut die technisch funktionierende sichtbar lassen).

Nun sind alle drei Elemente miteinander verbunden. Welches der Kindelemente am höchsten ist, drängt das Elternelement auf diese Höhe, und das andere Kindelement folgt. Das bedeutet, dass die Mindesthöhe des <textarea> die "Grundhöhe" wird, aber wenn das replizierte Textelement höher wächst, wächst alles mit.

So clever. Ich liebe es so sehr.

Sie müssen sicherstellen, dass das replizierte Element genau das gleiche ist

Gleiche Schriftart, gleicher Abstand, gleicher Rand, gleicher Rahmen… alles. Es ist eine identische Kopie, nur visuell versteckt mit visibility: hidden;. Wenn es nicht genau dasselbe ist, wird nicht alles genau richtig zusammen wachsen.

Wir brauchen auch white-space: pre-wrap; für den replizierten Text, da Textbereiche sich so verhalten.

Das ist der seltsamste Teil

In meiner Demo verwende ich ::after für den replizierten Text. Ich bin mir nicht sicher, ob das der bestmögliche Ansatz ist oder nicht. Es fühlt sich für mich sauber an, aber ich frage mich, ob die Verwendung eines <div aria-hidden="true"> für Screenreader sicherer ist? Oder reicht vielleicht visibility: hidden; dafür? So oder so, das ist nicht der seltsame Teil. Das ist der seltsame Teil

content: attr(data-replicated-value) " ";

Da ich ein Pseudoelement verwende, ist dies die Zeile, die das data-Attribut vom Element nimmt und den Inhalt auf der Seite rendert mit diesem zusätzlichen Leerzeichen (das ist der seltsame Teil). Wenn Sie das nicht tun, fühlt sich das Endergebnis "springend" an. Ich kann nicht sagen, dass ich es vollständig verstehe, aber es scheint, als ob es das Zeilenumbruchverhalten zwischen den Textbereichs- und Textelementen besser respektiert.

Wenn Sie kein Pseudoelement verwenden möchten, ist das in Ordnung für mich, aber achten Sie auf das springende Verhalten.


Besonderen Dank an Will Earp und Martin Tillmann, die beide am selben Tag zufällig eine E-Mail schrieben, um mich daran zu erinnern, wie clever Shaws Technik ist. Hier ist ein Beispiel, das Martin mit Alpine.js und Tailwind erstellt hat und das auch irgendwie zu einer Einzeiler-Lösung wird (aber beachten Sie, dass es das springende Problem hat).

Ich bin sicher, Sie alle können sich vorstellen, wie man dies mit Vue und React und ähnlichem umsetzt, um den Zustand zwischen einem Textbereich und einem anderen Element leicht beizubehalten. Ich werde hier keine Beispiele einfügen, teils weil ich faul bin, aber hauptsächlich, weil ich denke, dass Sie verstehen sollten, wie das funktioniert. Das macht Sie klüger und lässt Sie Ihre Website besser verstehen.