Otomatik yeniden boyutlandırma ile metin alanı oluşturma


366

Orada bu konuda başka bir iş parçacığı Denedim. Ancak bir sorun var: textareaiçeriği silerseniz küçülmez. Doğru boyuta küçültmek için herhangi bir yol bulamıyorum - clientHeightdeğer textarea, içeriğinin değil , tam boyutu olarak geri geliyor .

Bu sayfadaki kod aşağıdadır:

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

Bağladığınız konu için kabul edilen cevap benim için çalışıyor. Satır kesmeleri eklemek, metin alanını genişletir ve bunları kaldırmak metin alanını daraltır. Hangi tarayıcıyı kullanıyorsunuz?
EndangeredMassa

3
İşlevim hata veriyor. Satır sonuna mutlaka yeni satır yazılmalıdır. Bu daha iyi bir çözüm. james.padolsey.com/javascript/jquery-plugin-autoresize

Bunun için eklentimi deneyebilirsiniz: github.com/AndrewDryga/jQuery.Textarea.Autoresize
Andrew Dryga


Reakt kullanıyorsanız bunun için bir paket oluşturdum: npmjs.com/package/react-fluid-textarea
Martin Dawson

Yanıtlar:


230

Bu benim için çalışıyor (Firefox 3.6 / 4.0 ve 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>

Eğer jsfiddle üzerinde denemek istiyorsanız Tek bir satırla başlar ve sadece gerekli olan tam olarak büyür. Bir tek için Tamam textarea, ama ben böyle bir çok çok var bir şey yazmak istedim textarea(normalde bir büyük metin belgesi satırları kadar). Bu durumda gerçekten yavaş. (Firefox'ta bu inanılmaz derecede yavaş.) Bu yüzden gerçekten saf CSS kullanan bir yaklaşım istiyorum. Bu mümkün olabilircontenteditable , ama sadece düz metin olmasını istiyorum.


13
Öyle! Senin için bir jsfiddle yaptı: jsfiddle.net/CbqFv Şu anda Chrome, Firefox ve IE8'de çalışıyor - IE8'de biraz aksak olsa da. Satır sayısını arttırdıkça veya azalttıkça biraz düşüyor. JQuery için otomatik boyutlandırma eklentisinde görmüş olabileceğiniz gibi, metin alanını klonlayarak, orijinali yerine yüksekliğini otomatik olarak ayarlayıp ardından orijinalde kaydırma yüksekliğini ayarlamak için bunu kullanarak çalışırlar. Bu güncellenmiş kemanda bunu yaptım: jsfiddle.net/CbqFv/2 IE sorununu çözer, ancak Firefox çalışmayı durdurur.
Chris Moschini

3
@HelenNeely: O zaman kimlik kullanmayın. Örneğin bir sınıf kullanın ve init'in o sınıfın tüm öğeleri için ne yaptığını yapın. Bu yeni başlayan bir görev olmalı.
panzi

3
@ DenilsonSá Sadece modern tarayıcıların kullanıldığını varsayarsak web daha iyi bir yer olurdu.
panzi

2
IE11'de bir kaydırma çubuğu varsa bu iyi çalışmaz. Bu keman jsfiddle.net/CbqFv'yi kullanır ve kaydırma çubuğuna sahip olana kadar satırlar girerseniz bunu görürsünüz. Herhangi bir fikir?
kaljak

6
Metin alanı alt sayfa sonuna yakınsa bu tamamen kırılır - her şey nedeniyle ileri geri atlar style.height='auto'. Çözümün sadece ölçüm için kullanılan gizli bir kardeş eklemekten şüpheleniyorum.
rr-

372

TAM BİR EVET BASİT ÇÖZÜM

Güncelleme 2020-05-14 (Cep telefonları ve tabletler için geliştirilmiş tarayıcı desteği)

Aşağıdaki kod çalışacaktır:

  • Tuş girişinde.
  • Yapıştırılan metinle (sağ tıklayın & ctrl + v).
  • Metin kesme ile (sağ tıklama & ctrl + x).
  • Önceden yüklenmiş metin ile.
  • Tüm textarea (çok satırlı metin kutusu) sitesi genişliğinde.
  • İle Firefox (v31-67 test).
  • İle Chrome (v37-74 test).
  • İle IE (v9-V11 test edildi).
  • İle Kenar (V14-V18 test).
  • İle IOS Safari .
  • İle Android Tarayıcı .
  • JavaScript katı modu ile .
  • W3C geçerli kıldı.
  • Ve akıcı ve verimli.

SEÇENEK 1 (jQuery ile)

Bu seçenek jQuery gerektirir ve test edilmiştir ve 1.7.2 - 3.3.1 ile çalışmaktadır.

Basit (Bu jquery kodunu ana kod dosyanıza ekleyin ve unutun.)

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


SEÇENEK 2 (Saf JavaScript)

Basit (Bu JavaScript'i ana komut dosyanıza ekleyin ve unutun.)

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


SEÇENEK 3 (jQuery Uzantısı)

Otomatik boyutta olmasını istediğiniz textareas'a daha fazla zincir uygulamak istiyorsanız kullanışlıdır.

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

İle çağır $('textarea').autoHeight()


JAVASCRIPT İLE TEKSTİL GÜNCELLEME

JavaScript aracılığıyla bir metin alanına içerik enjekte ederken seçenek 1'deki işlevi çağırmak için aşağıdaki kodu ekleyin.

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

PRESET TEXTAREA YÜKSEKLİĞİ

Metin alanının başlangıç ​​yüksekliğini düzeltmek için ek bir koşul eklemeniz gerekir:

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
Bu harika bir çözüm, yöntem adı ve parametre adı tek tek harfler yerine gerçek adlar olarak güncellendiğinde biraz daha anlaşılır olurdu.
Chris Marisic

5
@Obsidian Teşekkürler! Az önce neden her zaman 0 elde ettiğimi anladım —— textarea'yı bir Bootstrap modeline koydum! Modal ilk başta gizlendiğinden, içindeki textarea 0 scrollHeight 😂😂
WTIFS

7
@Obsidian Fantastik !! (Seçenek 3). this.style.height = 'auto';Sihirli davranış düzeltmedir. ScrollHeight'ın davranışta neden bu kadar garip olduğu konusunda çok sinirliydim. Otomatik yükseklik, ardından aynı oluşturma döngüsünde scrollHeight ile eşleştirme, yalnızca ikinci yüksekliği teknik olarak boyaması gerekse de bu sorunu nasıl 'düzelttiğini' aklımıza getiriyor.
biraz daha az

2
Bugün Chrome'da 3. seçeneği denedim ve birkaç ince ayar yapmak zorunda kaldım. 1) Metin alanında "yükseklik" veya "tümü" geçişiniz varsa her zaman doğru şekilde yeniden boyutlandırılmaz. Yüksekliği etkileyen geçişleri kullanmamanızı tavsiye ederim. 2) scrollHeight, iki satır yüksekliğinde bir minumum döndürüyordu (belki de Chrome'daki textareas için varsayılan olduğu için), ancak bunu değiştirirseniz. Style.height = 'auto'; this.style.height = '0px'; ve başlangıç ​​durumunun gerçekten 0'a gitmesini önlemek için bir minimum yükseklik ekleyin, scrollHeight uygun olduğunda bir yükseklik satırını doğru şekilde döndürür.
ZorroDeLaArena

3
@Obsidian scrollHeight'ın this.style.height = 'auto';davranışını nasıl düzelttiğini açıklayabilir misiniz? Sadece sihir.
sidney

63

jQuery çözümü css gereksinimlerinize uyacak şekilde ayarlayın

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

VEYA jQuery 1.7 + için alternatif ...

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

Deneyleriniz için bir başlangıç ​​noktası olarak mutlak minimum stil ile bir keman yarattım ... http://jsfiddle.net/53eAy/951/


5
Bu iyi, ama overflow-y: hidden;yeniden boyutlandırma meydana geldiğinde kaydırma çubuğunun kısa bir süre yanıp sönmesini önlemek için css eklemek istiyorum .
brettjonesdev

Tamamen emin değilim, ancak onsuz metin alanı çok fazla büyür. Sanırım scrollHeight öğelerinin hesaplanmasıyla ilgilidir.
chim

1
Geniş senaryo $('textarea.auto-resize').on('change cut paste drop keyup', function(){...})
sahnesiyle

1
Görünüm penceresinden daha uzun metinlerde Chrome 40 Win 8.1'de çılgınca atlar. Oldukça kullanılamaz hale getirir.
tobibeer

1
Enter (satırsonu) basılı tutulursa kaydırma yapılır. Anahtar bırakılana kadar boyut ayarlanmaz.
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>

Firefox 14 ve Chromium 18'de test edildi. 24 ve 12 sayıları keyfidir, size en uygun olanı test edin.

Stil ve komut dosyası etiketleri olmadan yapabilirsiniz, ancak biraz dağınık imho olur (bu eski stil HTML + JS ve teşvik edilmez).

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

Düzenleme: modern kod. Onkeyup özelliği addEventListener olarak değiştirildi.
Edit: keydown keyup daha iyi çalışır Edit: declation
fonksiyon kullanmadan önce beyan
: input keydown daha iyi çalışır (thnx @ WASD42 & @ MA-Maddin)

jsfiddle


3
Bunun bazı dezavantajları vardır: 1) Textarea yeniden boyutlandırılmaz, daha sonra kullanıcı sadece fare düğmeleriyle bir şey yapıştırır; 2) Kullanıcı klavye (Ctrl + V) kullanarak bir şey yapıştıracaksa, textarea yalnızca Ctrl'yi serbest bırakacağı zaman yeniden boyutlandırılır. Kullanıcı Ctrl + V tuşlarına birkaç kez basarsa, metin alanı yalnızca sonuncusundan sonra büyür. Olayları yapıştırmak, kesmek, değiştirmek ve bırakmak için de aynı işlevi eklemelisiniz.
WASD42

Bu yüzden sadece inputetkinliği kullanın. Bkz. Stackoverflow.com/a/14029861/1951524
Martin Schneider

textareaTek astar olarak çoklu destek ile geliştirilmiş sürüm :document.querySelectorAll('textarea').forEach(function(te){ te.addEventListener("input", function() { this.style.height='24px'; this.style.height=this.scrollHeight+12+'px'; }); });
Meisner

1
@Meisner Daha kısa, ama "geliştirilmiş" olduğunu söyleyemem. Anonim bir işlevle, removeEventListenerolay dinleyicilerinizi aramanın ve temizlemenin bir yolu yoktur . Bu, forEach döngüsünün her yerinde olay dinleyicileri oluştururken özellikle önemlidir. Artı, benim görüşüme göre, okunabilirlik kısalıktan çok daha önemlidir.
GijsjanB

diğerleri ve gelecekteki benim için, box-sizing: border-box;özelliğin ayarlandığından emin olun, aksi takdirde textarea her onInput olayı için 4 piksellik bir alanı dışa aktarır. Bu sorun olduğunu anladım kadar 3 saat gibi geçirdi.
nöropatinin

24

Benim için en iyi çözüm (işe yarıyor ve kısa):

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

Macunla (fare ile de) yanıp sönmeden, çekerek, girerek ve doğru boyuta küçülmeden bir cazibe gibi çalışır.

Lütfen jsFiddle'a bir göz atın .


Müthiş!!! bir satır anlaşma! aptalca soru ho Yeniden boyutlandırıldığında bir animasyon ekleyebilir miyim? metin kutusu gibi hafifçe yeniden boyutlandırma atlamak yerine yeniden boyutlandırma?
user2513846

1
@ user2513846 Görünüşe göre çok satırlı düzenleme tasarımıyla mümkün değil. Ben textarea boyutu animasyon bir örnek yaptım: jsfiddle.net/yk2g333e Bildiğiniz gibi metin imleci satır ve çizgi veya caret iner, yani şu anda bir duraklama varsa canlandıracak bir şey yok. Ancak duraklama, kullanıcı için rahatsız edici olacaktır.
vatavale

1
@ user2513846 Bununla birlikte, textarea'nın sonunda bir satır daha boşsa, düzgün bir animasyona sahip olmak mümkündür: jsfiddle.net/p23erdfr
vatavale

16

Geçerli clientHeight ve yüksek kaliteli scrollHeight değerlerini kullanıyorsunuz. ScrollHeight'ı içeriği kaldırarak küçülttüğünüzde, önceden style.height tarafından ayarlanan clientHeight açık tuttuğu için hesaplanan alan küçülemez. Bunun yerine, textarea.rows öğesinden önceden tanımladığınız veya hesapladığınız bir max () scrollHeight ve minimum yükseklik değeri alabilirsiniz.

Genel olarak form kontrollerinde scrollHeight'a gerçekten güvenmemelisiniz. HTML / CSS, scrollHeight'ın diğer IE uzantılarından bazılarından daha az yaygın olarak desteklenmesinin yanı sıra, form denetimlerinin dahili olarak nasıl uygulandığı ve hiçbir şeyin scrollHeight'ın anlamlı olacağı konusunda garanti edilmediğiniz konusunda hiçbir şey söylemez. (Geleneksel olarak bazı tarayıcılar görev için işletim sistemi widget'ları kullandılar ve içlerindeki CSS ve DOM etkileşimini imkansız hale getirdi.) Efekti etkinleştirmeye çalışmadan önce en azından scrollHeight / clientHeight'ın varlığını koklayın.

Daha geniş bir şekilde çalışması önemliyse sorunu önlemek için bir başka olası alternatif yaklaşım, metinle aynı genişliğe sahip ve aynı yazı tipinde ayarlanmış gizli bir div kullanmak olabilir. Tuş takımında, metni metin alanından gizli div içindeki bir metin düğümüne kopyalarsınız ('\ n' karakterini satır sonu ile değiştirmeyi unutmayın ve innerHTML kullanıyorsanız '<' / '&' öğesinden düzgün bir şekilde kaçarsınız). Ardından div'in ofsetHeight değerini ölçmeniz, ihtiyacınız olan yüksekliği size verecektir.


1
Hangi tarayıcıların scrollHeighttextareas için problemleri var ? IE, Firefox ve Opera'nın güncel sürümleriyle iyi çalışıyor ...
Christoph

1
Tek yapmam gereken, clientHeight'ı scrollHeight olarak döndüren Konqueror. Bu, tarayıcı CSS kutusu modelini widget'ların içlerine uygulamadığı, her zaman yapmadıkları bir şey olmadığı ve standartların yapmaları gerektiğini söylemediği sürece bekleyebileceğiniz bir davranıştır.
bobince

14

IE8'i desteklemeniz gerekmiyorsa, inputetkinliği kullanabilirsiniz :

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

Şimdi sadece biraz CSS eklemeniz gerekiyor ve işiniz bitti:

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

Kullanımı:

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

Blog yayınımda nasıl çalıştığı hakkında daha fazla bilgi edinebilirsiniz .


1
Güzel bir çözüm, ama biraz düzeltme gerekiyor. Metin alanı içeriği yüklendiğinde f.ex. veritabanından, textarea küçük kalmak. Her inputforeach döngüsünde başlatma sırasında olayı tetiklemelisiniz .
Ajax

11

autosize

https://github.com/jackmoore/autosize

Sadece çalışır, bağımsız, popüler (Ekim 2018 itibariyle 3.0k + GitHub yıldızları), cdnjs'de mevcut ) ve hafif (~ 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>

BTW, ACE düzenleyicisini kullanıyorsanız maxLines: Infinityşunları kullanın : Ace Cloud 9 düzenleyicisindeki içeriğe yüksekliği otomatik olarak ayarlama


2
Sürüm 2 Şubat 2015'te piyasaya sürüldü. Daha basit hale geldi ve artık
çıtır

Üzgünüm, işe yarıyor. Belki başka bir tarayıcıdaydım .. Bu yüzden,
yorumumu

@ToniMichelCaubet ah, tamam belki CDN sorunu. Kontrol edeyim.
Ciro Santilli 法轮功 15: 六四 事件 法轮功

autosizeEklenti elle textarea yeniden boyutlandırma simgesini kullanarak yeniden boyutlandırmak için izin vermez.
j4v1

7

Buradan bir astar bulundu ;

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

6

Herkes düşünülebilir mi? Kaydırma ile uğraşmak yok, bu yüzden sevdiğim tek JS, verileri bulanıklıkta kaydetmeyi planlıyorsanız ... ve görünüşe göre, tüm popüler tarayıcılarda uyumludur: http://caniuse.com/#feat contenteditable =

Bir metin kutusu gibi görünmesi için stil verin ve otomatik olarak boyutlandırır ... Min yüksekliğini tercih edilen metin yüksekliğine getirin ve ona sahip olun.

Bu yaklaşımla ilgili güzel olan şey, bazı tarayıcılara kaydedip etiketleyebilmenizdir.

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, ENTER'a <div> öğeleri ekleyecek.
sbaechler

contenteditableiyidir, ancak düz metin istiyorsanız -webkit-user-modify: read-write-plaintext-onlyve gibi bir grup seçeneğe ihtiyaç duyar white-space: pre-wrap.
mik01aj

@_sbaechler: <div> ler kullanılırken çıkarılır [dom-element].innerText. @WebmasterG IMHO jquery'yi (saydamlık için) atlamak ve bu sayfaya jsfiddle yerine runnable Code Snippet'i ile örnek eklemek güzel olurdu.
adabru

4

Birden fazla textareas için aşağıdaki kodu kullandım. Textareas'ta gerçekleştirilen silme, kesme ve yapıştırma işlemleriyle bile Chrome 12, Firefox 5 ve IE 9'da iyi çalışıyor.

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

Biraz farklı bir yaklaşım var.

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

Fikir metni textareaiçine kopyalamak preve CSS'nin aynı boyutta olduğundan emin olmasını sağlamaktır.

Bunun yararı, çerçevelerin metni hiçbir olaya dokunmadan hareket ettirmek için basit araçlar sunmasıdır. Yani, angularjs içinde bir eklersiniz ng-model="foo" ng-trim="false"için textareave ng-bind="foo + '\n'"için pre. Bir keman görün .

Bunun preile aynı yazı tipi boyutuna sahip olduğundan emin olun textarea.


1
" Sadece bununla preaynı yazı tipi boyutuna sahip olduğundan emin oluntextarea " - Aynı ve / veya line-heighteşit miktarda gerekir . Bu, Angular için en iyi çözümdür. paddingborder
Jamie Barker

4

Aşağıdakiler, bu eylemlerin fareden, klavye kısayolundan, menü çubuğundan bir seçenek seçip seçmekten bağımsız olarak kesme, yapıştırma vb. İçin çalışır ... birkaç cevap benzer bir yaklaşım benimser ancak boyutlandırma, bu yüzden stili yanlış uyguluyorlar overflow: hidden .

Aşağıdakileri yapıyorum, bu da minimum ve maksimum yükseklik için max-heightve iyi çalışıyor rows.

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>

Mutlak bütünlük için, adjustişlevi birkaç durumda daha çağırmalısınız :

  1. Pencere yeniden boyutlandırmasıyla yapılan textareadeğişikliklerin genişliği veya metin alanının genişliğini değiştiren diğer olaylar varsa pencere yeniden boyutlandırma olayları
  2. Ne zaman textareabireyin displaytarzı nitelik değişiklikleri, mesela o gider none(gizli) içinblock
  3. Değerinin textareaprogramlı olarak değiştirilmesi

Kullanmanın window.getComputedStyleveya almanın currentStylebiraz pahalıya mal olabileceğini unutmayın, bunun yerine sonucu önbelleğe almak isteyebilirsiniz.

IE6 için çalışıyor, bu yüzden bunun yeterince iyi bir destek olduğunu umuyorum.


4

Farklı bir yaklaşım olarak, <span>boyutunu otomatik olarak ayarlayan bir yöntem kullanabilirsiniz . contenteditable="true"Mülkü ekleyerek düzenlenebilir hale getirmeniz gerekecektir :

div {
  width: 200px;
}

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

Bu yaklaşımla ilgili tek sorun, değeri formun bir parçası olarak göndermek istiyorsanız, bunu JavaScript'te kendiniz yapmanız gerektiğidir. Bunu yapmak nispeten kolaydır. Örneğin, gizli bir alan ekleyebilir onsubmitve formun spanolması durumunda gizli alanın değerini atar ve bu alan otomatik olarak formla birlikte gönderilir.



@adabru Evet, ancak iki cevap aynı değil. Toyota kırmızı araba yapıyor ve Ford da kırmızı araba yapıyor, ama farklılar, değil mi? Diğer yanıtı daha çok beğenirseniz, cevap verin. Ama cevabımı daha fazla takdir eden ve onunla ilgilenenler var. Farklı seçeneklere sahip olmak iyidir.
Racil Hilan

3

Biraz düzeltmeler. Opera'da mükemmel çalışır

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

hatlarınız taşmadığı sürece çalışır - o zaman sığmazlar.
Tomáš Kafka

kutunun dışında çalışır, harika (firefox 72)
Mikeys4u

2

Ben jquery ile bunu uygulamak için kısa ve doğru bir yol biliyorum. Hiçbir ekstra gizli div gerekli ve çoğu tarayıcı çalışır

<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()kullanımdan kaldırıldı. api.jquery.com/live Genel olarak .on()bunun yerine kullanmak isteyeceksiniz .
Luke

2

Kimsenin bu şekilde bahsettiğini bilmiyorum ama bazı durumlarda yüksekliği satırlarla yeniden boyutlandırmak mümkün

textarea.setAttribute('rows',breaks);

gösteri


1
Bu sadece varsa çalışır white-space: nowrap;. Bir satır, satır kesmesi olmadan başka bir satıra sarıldığında, metin alanı artık doğru şekilde ayarlanmayacaktır.
Yeti

2

İşte panzi'nin cevabı için bir açısaljs direktifi.

 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>

SetTimout'tan $ timeout kullanmayı tercih etmelisiniz - bu, modelin başlatılmasını sağlar (milisaniye belirtmeye gerek yoktur - Açısal özet döngüsünden sonra yürütülür). Ayrıca element = element [0]; çok kötü bir uygulama ... Her neyse, çözüm benim için iyi değil çünkü daha fazla metin olana kadar tek satırlık tekdüze olmam gerekiyor.
Karol Websky

2

textareaYazarken JQuery'yi kullanabilirsiniz :

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


En temiz çözüm. ancak jQuery'i kullanmayı bırakmamız gerektiği gibi: textarea.addEventListener ('keyup', () => {textarea.style.height = 0; textarea.style.height = ${textarea.scrollHeight}px;});
Toni Michel Caubet

2

Angular'ın yeni versiyonlarında da aynı şeyi başarmak isteyenler.

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

Ayrıca, kullanıcı metin alanının yüksekliğini belirli bir yüksekliğe yükseltmek ve daha sonra overflow:scrollüzerinde olmak istediğinde, bazı kullanıcıların iş parçacığı okuma kullanışlı gelebilecek başka bir kullanım durumu ekliyorum , yukarıdaki yöntem belirtilen kullanım durumunu elde etmek için genişletilebilir.

  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

Buradaki cevapların bazıları doldurmayı hesaba katmıyor.

Gitmek istemediğiniz bir maksimum Yüksekliğiniz olduğunu varsayarsak, bu benim için çalıştı:

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

Daha da basit, daha temiz bir yaklaşım şudur:

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

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

Gereken tek şey , hedeflemek istediğiniz .auto-heightherhangi birine sınıfı eklemektir textarea.

FF, Chrome ve Safari'de test edildi. Bunun sizin için işe yarayıp yaramadığını bize bildirin. Ama, bu işe yaradığını bulduğum en temiz ve en basit yol. Ve harika çalışıyor! : D


Düzenledikten sonra metni kaldırmaya çalıştınız mı? Metin alanı çöktü mü?
18C

1

Bu kod yapıştırma ve silme seçeneğini de seçer.

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>

İşte JSFiddle


1

Javascript kütüphanesini http://javierjulio.github.io/textarea-autosize adresinden öneriyorum .

Yorum başına, eklenti kullanımına örnek kod bloğu ekleyin:

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

Gereken minimum CSS:

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

1

QQuery kullanan MakeTextAreaResisable

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

benim uygulama çok basit, giriş satır sayısını (ve bir textarea göstermek için en az 2 satır):

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

uyaranlı tam çalışma örneği: https://jsbin.com/kajosolini/1/edit?html,js,output

(ve bu, örneğin tarayıcının manuel yeniden boyutlandırma tutamacıyla çalışır)


2
Bu yalnızca satırı "enter" tuşuna basarak keserseniz çalışır. Metin, metin alanının genişliğinden daha uzun, ancak "enter" tuşuna basmazsanız, genişlemez.
Nathalia Xavier

1

Kabul edilen cevap iyi çalışıyor. Ancak bu basit işlevsellik için çok kod var. Aşağıdaki kod işinizi görecektir.

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

0

TextArea için MVC HTML Helper kullanırken ne yaptım. Birkaç textarea elementim vardı, bu yüzden Model Id kullanarak onları ayırmak zorunda kaldım.

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

ve komut dosyasında şunu ekledi:

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

IE10 ve Firefox23'te test ettim


0

Bu kodu kullanabilirsiniz:

coffeescript:

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();
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.