Tworzenie obszaru tekstowego z automatyczną zmianą rozmiaru

366

Był na ten temat kolejny wątek , który próbowałem. Ale jest jeden problem: textareanie zmniejsza się, jeśli usuniesz zawartość. Nie mogę znaleźć żadnego sposobu, aby zmniejszyć go do właściwego rozmiaru - clientHeightwartość wraca jako pełny rozmiar textarea, a nie jego zawartość.

Kod z tej strony znajduje się poniżej:

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 )
    };
}
DisgruntledGoat
źródło
Akceptowana odpowiedź dla wątku, który podłączyłeś, działa dla mnie. Dodanie podziałów linii powoduje rozszerzenie obszaru tekstowego i usunięcie go powoduje zmniejszenie obszaru tekstowego. Z jakiej przeglądarki korzystasz?
EndangeredMassa
3
Moja funkcja zawiera błąd. Konieczne jest wpisanie nowej linii na końcu linii. To lepsze rozwiązanie. james.padolsey.com/javascript/jquery-plugin-autoresize
Możesz wypróbować moją wtyczkę: github.com/AndrewDryga/jQuery.Textarea.Autoresize
Andrew Dryga
możliwy duplikat obszaru tekstowego
Ciro Santilli 法轮功 冠状 病 六四 事件 法轮功
Stworzyłem do tego pakiet, jeśli używasz reagować: npmjs.com/package/react-fluid-textarea
Martin Dawson

Odpowiedzi:

230

To działa dla mnie (Firefox 3.6 / 4.0 i 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>

Jeśli chcesz wypróbować na jsfiddle. Zaczyna się od pojedynczej linii i rośnie tylko niezbędna ilość. Jest to w porządku dla jednego singla textarea, ale chciałem napisać coś, w którym miałbym wiele, wiele takich textarea(mniej więcej tyle, ile normalnie miałyby linie w dużym dokumencie tekstowym). W takim przypadku jest to naprawdę powolne. (W przeglądarce Firefox jest niesamowicie powolny.) Naprawdę chciałbym zastosować podejście, które wykorzystuje czysty CSS. Byłoby to możliwe contenteditable, ale chcę, aby było to tylko zwykły tekst.

panzi
źródło
13
To robi! Stworzyłem jsfiddle dla ciebie: jsfiddle.net/CbqFv Działa teraz w Chrome, Firefox i IE8 - chociaż w IE8 jest trochę usterka. Gdy zwiększasz lub zmniejszasz liczbę linii, trochę to przeraża. Jak zapewne widzieliście we wtyczce autoresize dla jQuery, omijają to, klonując obszar tekstowy, ustawiając jego wysokość na auto zamiast oryginału, a następnie używając go do ustawienia wysokości przewijania na oryginale. Zrobiłem to w tym zaktualizowanym fiddle: jsfiddle.net/CbqFv/2 Rozwiązuje problem IE, ale Firefox przestaje działać.
Chris Moschini,
3
@HelenNeely: Więc nie używaj identyfikatora. Np. Użyj klasy i rób to, co init robi dla wszystkich elementów tej klasy. To powinno być zadanie dla początkujących.
panzi
3
@ DenilsonSá Gdyby tylko można było założyć, że używane są tylko nowoczesne przeglądarki, lepszym miejscem byłoby Internet.
panzi
2
To nie zadziała dobrze, jeśli pasek przewijania jest włączony w IE11. Jeśli użyjesz tego skrzypce jsfiddle.net/CbqFv i wprowadzisz wiersze, dopóki nie pojawi się pasek przewijania, zobaczysz go. Jakieś pomysły?
kaljak
6
To się całkowicie psuje, jeśli obszar tekstowy znajduje się w pobliżu końca dolnej strony - wszystko przeskakuje do tyłu i do przodu z powodu style.height='auto'. Podejrzewam, że rozwiązaniem jest dodanie ukrytego rodzeństwa używanego tylko do pomiaru.
rr-
372

KOMPLETNE JESZCZE PROSTE ROZWIĄZANIE

Zaktualizowano 2020-05-14 (Poprawiona obsługa przeglądarki dla telefonów komórkowych i tabletów)

Działa następujący kod:

  • Po wprowadzeniu klucza.
  • Z wklejonym tekstem (kliknij prawym przyciskiem i ctrl + v).
  • Z wyciętym tekstem (kliknij prawym przyciskiem i ctrl + x).
  • Z fabrycznie załadowanym tekstem.
  • Ze wszystkimi stronami tekstowymi (wieloliniowe pola tekstowe) .
  • Z Firefoksem (przetestowano v31-67).
  • Z Chrome (testowane w wersji 37–74).
  • Z IE (testowane w wersji v9-v11).
  • Z Edge (testowane w wersji v14-v18).
  • Z IOS Safari .
  • Z przeglądarką Android .
  • W trybie ścisłym JavaScript .
  • Jest sprawdzony w3c .
  • I jest usprawniony i wydajny.

OPCJA 1 (z jQuery)

Ta opcja wymaga jQuery i została przetestowana i działa z wersjami 1.7.2 - 3.3.1

Prosty (Dodaj ten kod jquery do głównego pliku skryptu i zapomnij o nim).

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


OPCJA 2 (czysty JavaScript)

Proste (dodaj ten kod JavaScript do głównego pliku skryptu i zapomnij o nim).

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


OPCJA 3 (rozszerzenie jQuery)

Przydatne, jeśli chcesz zastosować dalsze tworzenie łańcuchów w obszarach tekstowych, w których chcesz automatycznie zmieniać rozmiar.

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

Wywołaj z $('textarea').autoHeight()


AKTUALIZACJA TEXTAREA PRZEZ JAVASCRIPT

Podczas wstrzykiwania treści do obszaru tekstowego za pomocą JavaScript dołącz następujący kod, aby wywołać funkcję w opcji 1.

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

WSTĘPNA WYSOKOŚĆ TEKSTAREA

Aby naprawić początkową wysokość obszaru tekstowego, musisz dodać dodatkowy warunek:

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>

DreamTeK
źródło
12
To świetne rozwiązanie, byłoby nieco bardziej zrozumiałe, gdyby nazwa metody i nazwa parametru zostały zaktualizowane, aby były prawdziwymi nazwami zamiast pojedynczych liter.
Chris Marisic
5
@Obsidian Thanks! Właśnie zorientowałem się, dlaczego zawsze dostaję 0 —— umieszczam textarea w module Bootstrap! Ponieważ modal jest początkowo ukryty, obszar
tekstowy
7
@Obsidian Fantastic !! (Opcja 3). To this.style.height = 'auto';jest poprawka magicznego zachowania. Byłem tak sfrustrowany, dlaczego scrollHeight był tak dziwny w zachowaniu. Wysokość automatyczna, a następnie dopasowanie scrollHeight w tym samym cyklu renderowania wciąż mnie zastanawia, jak to „naprawia” ten problem, chociaż technicznie powinien malować tylko drugą wysokość.
bitów,
2
Wypróbowałem dzisiaj opcję 3 w Chrome i musiałem wprowadzić kilka poprawek. 1) Nie zawsze zmienia się rozmiar, jeśli masz przejście „wzrost” lub „wszystko” w obszarze tekstowym. Polecam nie używać przejść, które wpływają na wysokość. 2) ScrollHeight zwrócił minumum o wysokości dwóch wierszy (być może dlatego, że jest to domyślne ustawienie dla obszarów tekstowych w Chrome), ale jeśli zmienisz this.style.height = 'auto'; to this.style.height = '0px'; i dodaj minimalną wysokość, aby nie dopuścić do faktycznego stanu początkowego 0, scrollHeight zwróci poprawnie jeden wiersz wysokości, gdy jest to właściwe.
ZorroDeLaArena
3
@Obsidian Czy możesz wyjaśnić, w jaki sposób this.style.height = 'auto';naprawia zachowanie scrollHeight? To tylko magia.
sidney,
63

Rozwiązanie jQuery dostosowuje css do twoich wymagań

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

LUB alternatywa dla jQuery 1.7 + ...

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

Jako punkt wyjścia do eksperymentów stworzyłem skrzypce z absolutnie minimalnym stylem. Http://jsfiddle.net/53eAy/951/

chim
źródło
5
To dobrze, ale dodałbym overflow-y: hidden;do css, aby zapobiec krótkiemu miganiu paska przewijania, gdy nastąpi zmiana rozmiaru.
brettjonesdev
Nie do końca pewny, ale bez tego obszar tekstowy rośnie zbyt mocno. Myślę, że ma to związek ze sposobem obliczania elementów scrollHeight.
Chim
1
Użyj wielu wydarzeń, aby przygotować scenariusz do $('textarea.auto-resize').on('change cut paste drop keyup', function(){...})
pełnej wiarygodności
1
Skacze jak szalony w Chrome 40 Win 8.1 na tekstach dłuższych niż okienko ekranu. Renderuje to całkiem bezużyteczne.
tobibeer
1
Przytrzymanie klawisza Enter (nowa linia) powoduje przewijanie. Rozmiar nie zmienia się, dopóki klucz nie zostanie zwolniony.
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>

Testowane w Firefox 14 i Chromium 18. Liczby 24 i 12 są dowolne, przetestuj, aby sprawdzić, co najbardziej Ci odpowiada.

Możesz obejść się bez tagów stylu i skryptu, ale staje się nieco niechlujny imho (jest to stary styl HTML + JS i nie jest zachęcany).

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

Edycja: zmodernizowany kod. Zmieniono atrybut onkeyup na addEventListener.
Edycja: keydown działa lepiej niż keyup
Edycja: deklaracja funkcji przed użyciem
Edycja: wejście działa lepiej niż keydown (thnx @ WASD42 i @ MA-Maddin)

jsfiddle

GijsjanB
źródło
3
Ten ma pewne wady: 1) Rozmiar obszaru tekstowego nie zostałby zmieniony, a następnie użytkownik wkleił coś tylko za pomocą przycisków myszy; 2) Jeśli użytkownik wklei coś za pomocą klawiatury (Ctrl + V), obszar tekstowy zostanie przeskalowany tylko wtedy, gdy zwolni Ctrl. Jeśli użytkownik naciśnie Ctrl + V kilka razy, obszar tekstowy rozrośnie się dopiero po ostatnim. Powinieneś dodać tę samą funkcję do wklejania, wycinania, zmiany i upuszczania zdarzeń.
WASD42
inputZamiast tego skorzystaj z wydarzenia. Zobacz stackoverflow.com/a/14029861/1951524
Martin Schneider
Ulepszona wersja z wieloma textareawsparciem jako jednej linijki:document.querySelectorAll('textarea').forEach(function(te){ te.addEventListener("input", function() { this.style.height='24px'; this.style.height=this.scrollHeight+12+'px'; }); });
Meisner
1
@ Meisner Jest krótszy, ale nie powiedziałbym, że jest „ulepszony”. Dzięki anonimowej funkcji nie ma sposobu, aby wywoływać removeEventListeneri czyścić detektory zdarzeń. Jest to szczególnie ważne przy tworzeniu detektorów zdarzeń w dowolnym miejscu w pętli forEach. Ponadto, moim zdaniem, czytelność jest znacznie ważniejsza niż zwięzłość.
GijsjanB,
dla innych i dla mnie przyszłości upewnij się, że box-sizing: border-box;właściwość jest ustawiona, w przeciwnym razie obszar tekstowy powiększy się o 4px dla każdego zdarzenia onInput. Spędziłem około 3 godzin, dopóki nie zorientowałem się, że to jest problem.
AI.
24

Najlepsze rozwiązanie (działa i jest krótkie) dla mnie to:

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

Działa jak urok bez mrugania pastą (również myszą), cięcia, wchodzenia i kurczy się do odpowiedniego rozmiaru.

Proszę spojrzeć na jsFiddle .

Vatavale
źródło
Przerażający!!! oferta jednej linii! głupie pytanie, czy mogę dodać animację, gdy zmieni się rozmiar? jak pole tekstowe delikatnie zmienia rozmiar zamiast przeskakiwać do rozmiaru?
user2513846
1
@ user2513846 Wygląda na to, że projekt edycji wielu wierszy nie jest możliwy. Zrobiłem przykład animacji rozmiaru obszaru tekstowego : jsfiddle.net/yk2g333e Jak wiadomo kursor tekstowy przesuwa się w dół na końcu linii lub karetki, więc jeśli nie ma przerwy w tym momencie, nie ma nic do animacji. Ale wstrzymanie będzie denerwujące dla użytkownika.
vatavale
1
@ user2513846 Jednak z jeszcze jedną pustą linią na końcu pola
tekstowego
16

Używasz wyższej wartości bieżącego clientHeight i content scrollHeight. Gdy zmniejszysz scrollHeight poprzez usunięcie zawartości, obliczony obszar nie może się zmniejszyć, ponieważ clientHeight, wcześniej ustawiony przez style.height, utrzymuje go otwartym. Zamiast tego możesz wziąć max () scrollHeight i minimalną wartość wysokości, którą wcześniej zdefiniowałeś lub obliczyłeś z textarea.rows.

Ogólnie rzecz biorąc, prawdopodobnie nie powinieneś polegać na scrollHeight na kontrolkach formularzy. Oprócz tego, że scrollHeight jest tradycyjnie mniej obsługiwany niż niektóre inne rozszerzenia IE, HTML / CSS nie mówi nic o tym, jak formanty formularzy są implementowane wewnętrznie i nie ma gwarancji, że scrollHeight będzie miał jakiekolwiek znaczenie. (Tradycyjnie niektóre przeglądarki używają do tego zadania widżetów systemu operacyjnego, co uniemożliwia interakcję CSS i DOM na ich elementach wewnętrznych.) Przynajmniej wąchaj istnienie scrollHeight / clientHeight przed próbą włączenia efektu.

Innym możliwym alternatywnym podejściem do uniknięcia problemu, jeśli ważne jest, aby działał szerzej, może być użycie ukrytego elementu div o tej samej szerokości co obszar tekstowy i ustawienie tej samej czcionki. Przy wprowadzaniu klucza kopiujesz tekst z obszaru tekstowego do węzła tekstowego w ukrytym div (pamiętając o zastąpieniu „\ n” znakiem podziału linii i odpowiednio „+” i „+”, jeśli używasz innerHTML). Następnie wystarczy zmierzyć przesunięcie divWysokość da ci potrzebną wysokość.

Bobin
źródło
1
Z jakimi przeglądarkami mają wystąpić problemy z scrollHeightobszarami tekstowymi? Działa dobrze z aktualnymi wersjami IE, Firefox i Opera ...
Christoph
1
Jedyne, co muszę podać, to Konqueror, który zwraca wartość clientHeight jako scrollHeight. Jest to zachowanie, którego można się spodziewać, chyba że przeglądarka zastosuje model pudełkowy CSS do wewnętrznych elementów widgetów, czego nie zawsze robili, a standard nie mówi, że muszą.
Bobin
14

Jeśli nie potrzebujesz obsługiwać IE8, możesz użyć inputzdarzenia:

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

Teraz wystarczy tylko dodać trochę CSS i gotowe:

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

Stosowanie:

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

Możesz przeczytać więcej o tym, jak to działa na moim blogu .

Maksymilian Hoffmann
źródło
1
Ładne rozwiązanie, ale wymaga niewielkiej naprawy. Po załadowaniu zawartości pola tekstowego np. z bazy danych textarea pozostają małe. Musisz zainicjować inputzdarzenie podczas inicjalizacji w cyklu foreach.
Ajax,
11

rozmiar auta

https://github.com/jackmoore/autosize

Po prostu działa, samodzielny, jest popularny (3,0 tys. + Gwiazdy GitHub od października 2018 r.), Dostępny na cdnjs ) i lekki (~ 3,5 tys.). Próbny:

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

BTW, jeśli używasz edytora ACE, użyj maxLines: Infinity: Automatycznie dostosuj wysokość do zawartości w edytorze Ace Cloud 9

Ciro Santilli
źródło
2
Wersja 2 została wydana w lutym 2015 roku. Stała się prostsza i nie zależy już od jQuery
chrupiące
Przepraszamy, to działa. Może byłem w innej przeglądarce ... więc myślę, że lepiej zignorować mój komentarz ..
Toni Michel Caubet
@ToniMichelCaubet ah, OK, może więc problem z CDN. Niech sprawdzę.
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
autosizePlugin nie pozwala na zmianę rozmiaru ręcznie za pomocą ikony zmiany rozmiaru w textarea.
j4v1
7

Znalazłem stąd jeden liniowiec ;

<textarea name="text" oninput="this.style.height = ''; this.style.height = this.scrollHeight +'px'"></textarea>
17 tys
źródło
6

Czy ktoś uznał za zadowalające? Bez przewijania przy przewijaniu, a jedynym JS, który mi się podoba, jest to, jeśli planujesz zapisać dane na rozmyciu ... i najwyraźniej jest kompatybilny ze wszystkimi popularnymi przeglądarkami: http://caniuse.com/#feat = zadowalający

Wystarczy nadać mu styl, aby wyglądał jak pole tekstowe, i automatycznie się zmienia ... Ustaw minimalną wysokość na preferowaną wysokość tekstu i ustaw ją.

Fajne w tym podejściu jest to, że możesz zapisywać i tagować w niektórych przeglądarkach.

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>
Webmaster G
źródło
Chrome doda elementy <div> przy ENTER.
sbaechler
contenteditablejest dobry, ale jeśli chcesz w postaci zwykłego tekstu, potrzebujesz wielu opcji takich jak -webkit-user-modify: read-write-plaintext-onlyi white-space: pre-wrap.
mik01aj
@_sbaechler: <div> s są pomijane podczas używania [dom-element].innerText. @WebmasterG IMHO byłoby miło pominąć jquery (dla przejrzystości) i dołączyć przykład na tej stronie poprzez uruchamiany fragment kodu zamiast w jsfiddle.
adabru
4

Użyłem następującego kodu dla wielu obszarów tekstowych. Działa dobrze w Chrome 12, Firefox 5 i IE 9, nawet z działaniami usuwania, wycinania i wklejania wykonywanymi w obszarach tekstowych.

<!-- 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>
Nikunj Bhatt
źródło
4

Istnieje nieco inne podejście.

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

Chodzi o to, aby skopiować tekst z textareaInto thepre i niech CSS upewnij się, że mają ten sam rozmiar.

Korzyścią jest to, że frameworki oferują proste narzędzia do przenoszenia tekstu bez dotykania żadnych zdarzeń. Mianowicie, w AngularJS dodajesz a ng-model="foo" ng-trim="false"do textareai ng-bind="foo + '\n'"do pre. Zobacz skrzypce .

Tylko upewnij się, że prema taki sam rozmiar czcionki jak textarea.

Karolis Juodelė
źródło
1
Upewnij się tylko, że prema taki sam rozmiar czcionki jaktextarea ” - Potrzebują tego samego line-heighti równej ilości paddingi / lub borderteż. To najlepsze rozwiązanie dla Angulara.
Jamie Barker,
4

Poniższe czynności służą do wycinania, wklejania itp., Niezależnie od tego, czy te działania są wykonywane za pomocą myszy, skrótu klawiaturowego, wybrania opcji z paska menu ... kilka odpowiedzi przyjmuje podobne podejście, ale nie uwzględnia pola rozmiaru, dlatego nieprawidłowo stosują styl overflow: hidden.

I wykonaj następujące czynności, która również działa dobrze max-heighti rowsdla minimalnej i maksymalnej wysokości.

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>

Aby uzyskać całkowitą kompletność, należy wywołać adjustfunkcję w kilku innych okolicznościach:

  1. Zdarzenia textareazmieniają rozmiar okna, jeśli szerokość zmian wraz ze zmianą rozmiaru okna lub inne zdarzenia zmieniające szerokość obszaru tekstowego
  2. Kiedy textarea„s displayzmiany atrybutów stylu, np gdy idzie z none(ukryte) doblock
  3. Gdy wartość parametru textareazmienia się programowo

Pamiętaj, że używanie window.getComputedStylelub pobieranie currentStylemoże być nieco kosztowne obliczeniowo, więc zamiast tego możesz chcieć buforować wynik.

Działa dla IE6, więc naprawdę mam nadzieję, że to wystarczająco dobre wsparcie.

Joseph Nields
źródło
4

Jako inne podejście możesz użyć narzędzia, <span>które automatycznie dostosowuje jego rozmiar. Będziesz musiał go edytować, dodając contenteditable="true"właściwość i gotowe:

div {
  width: 200px;
}

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

Jedynym problemem związanym z tym podejściem jest to, że jeśli chcesz przesłać wartość jako część formularza, musisz to zrobić samodzielnie w JavaScript. Jest to stosunkowo łatwe. Na przykład możesz dodać ukryte pole, aw onsubmitprzypadku formularza przypisać wartość spando ukrytego pola, które zostanie następnie automatycznie przesłane z formularzem.

Racil Hilan
źródło
Na tej stronie jest już odpowiedź wykorzystująca contenteditable: stackoverflow.com/questions/454202/…
adabru
@adabru Tak, ale dwie odpowiedzi nie są takie same. Toyota produkuje czerwone samochody, a Ford także czerwone samochody, ale są różne, prawda? Jeśli podoba Ci się inna odpowiedź, wybierz ją. Ale są tacy, którzy bardziej doceniają moją odpowiedź i idą za nią. Dobrze jest mieć różne opcje.
Racil Hilan,
3

Trochę poprawek. Działa idealnie w Operze

  $('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;
  });
artnik-pro
źródło
działa, dopóki linie się nie przepełnią - wtedy nie będą pasować.
Tomáš Kafka
działa od
razu po
2

Znam krótki i prawidłowy sposób implementacji tego za pomocą jquery. Nie jest wymagany żaden dodatkowy ukryty div i działa on w większości przeglądarek

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

źródło
jQuery's .live()jest przestarzałe. api.jquery.com/live Zazwyczaj .on()zamiast tego będziesz chciał użyć .
Luke
2

Nie wiem, czy ktoś wspomina w ten sposób, ale w niektórych przypadkach można zmienić wysokość za pomocą wiersza Attribute

textarea.setAttribute('rows',breaks);

Próbny

h0mayun
źródło
1
Działa to tylko wtedy, gdy masz white-space: nowrap;. Kiedy linia zawija się do innej linii bez podziału linii, obszar tekstowy nie będzie już odpowiednio dopasowywany.
Yeti,
2

Oto dyrektywa angularjs dla odpowiedzi panzi.

 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>
chrmcpn
źródło
Powinieneś raczej użyć $ timeout niż setTimout - upewni się to, że model zostanie zainicjowany (nie trzeba określać milisekund - zostanie wykonany po cyklu Angular digest). Również element = element [0]; jest bardzo złą praktyką ... W każdym razie rozwiązanie nie jest dla mnie dobre, ponieważ potrzebuję, aby obszar tekstowy był jednowierszowy, dopóki nie będzie więcej tekstu.
Karol Websky,
2

Możesz użyć JQuery do rozszerzenia textareapodczas pisania:

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

Mauricio Sánchez
źródło
Najczystsze rozwiązanie. ale jak powinniśmy przestać używać jQuery: textarea.addEventListener ('keyup', () => {textarea.style.height = 0; textarea.style.height = ${textarea.scrollHeight}px;});
Toni Michel Caubet
2

Ci, którzy chcą osiągnąć to samo w nowych wersjach Angular.

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

Dodam również inny przypadek użycia, który może się przydać niektórym użytkownikom czytającym wątek, gdy użytkownik chce zwiększyć wysokość pola tekstowego do pewnej wysokości, a następnie mieć overflow:scrollna nim powyższą metodę można rozszerzyć, aby osiągnąć wspomniany przypadek użycia.

  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';
    }
  }
Divyanshu Rawat
źródło
1

Niektóre odpowiedzi tutaj nie uwzględniają wypełniania.

Zakładając, że masz maksymalną wysokość, której nie chcesz przekraczać, działało to dla mnie:

    // 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);
hasen
źródło
1

Jeszcze prostsze i czystsze podejście jest następujące:

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

// i 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
}

Wystarczy dodać .auto-heightklasę do dowolnego, na textareaktóry chcesz kierować.

Testowane w FF, Chrome i Safari. Daj mi znać, jeśli z jakiegoś powodu to nie zadziała. Ale to najczystszy i najprostszy sposób, w jaki udało mi się to osiągnąć. I działa świetnie! :RE

wskrzesić
źródło
Czy próbowałeś usunąć tekst po edycji? Czy obszar tekstowy się zawalił?
18C,
1

Ten kod działa podczas wklejania i wybierz również usuń.

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>

Oto JSFiddle

Kurenai Kunai
źródło
1

Polecam bibliotekę javascript z http://javierjulio.github.io/textarea-autosize .

W komentarzach dodaj przykładowy blok kodu dotyczący użycia wtyczki:

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

Minimalny wymagany CSS:

textarea {
  box-sizing: border-box;
  max-height: 160px; // optional but recommended
  min-height: 38px;
  overflow-x: hidden; // for Firefox (issue #5)
}
orange01
źródło
1

MakeTextAreaResisable, który używa qQuery

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();
}
Igor Krupicki
źródło
1

Żadna z odpowiedzi wydaje się nie działać. Ale ten działa dla mnie: https://coderwall.com/p/imkqoq/resize-textarea-to-fit-content

$('#content').on( 'change keyup keydown paste cut', 'textarea', function (){
    $(this).height(0).height(this.scrollHeight);
}).find( 'textarea' ).change();
Kim Homann
źródło
To powinna być zaakceptowana odpowiedź, choć wystarczy wysłuchać wydarzeń „keyup”
Bob Ross,
1

moja implementacja jest bardzo prosta, policz liczbę linii na wejściu (i minimum 2 wiersze, aby pokazać, że jest to obszar tekstowy):

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

pełny działający przykład z bodźcem: https://jsbin.com/kajosolini/1/edit?html,js,output

(i działa to na przykład z ręcznym uchwytem zmiany rozmiaru przeglądarki)

localhostdotdev
źródło
2
Działa to tylko wtedy, gdy przekroczysz linię, naciskając „enter”. Jeśli tekst jest dłuższy niż szerokość obszaru tekstowego, ale nie naciśniesz „enter”, nie będzie się on rozwijał.
Nathalia Xavier
1

Zaakceptowana odpowiedź działa poprawnie. Ale to dużo kodu dla tej prostej funkcjonalności. Poniższy kod załatwi sprawę.

   $(document).on("keypress", "textarea", function (e) {
    var height = $(this).css("height");
    var iScrollHeight = $(this).prop("scrollHeight");
    $(this).css('height',iScrollHeight);
    });
karthik_krish
źródło
0

Oto, co zrobiłem podczas korzystania z MVC HTML Helper dla TextArea. Miałem sporo elementów textarea, więc musiałem je rozróżnić za pomocą identyfikatora modelu.

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

i w skrypcie dodał to:

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

Przetestowałem to na IE10 i Firefox23

gunnerz
źródło
0

Możesz użyć tego kodu:

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();
Darex1991
źródło