Membuat textarea dengan auto-resize

366

Disana ada utas lain tentang ini , yang telah saya coba. Tapi ada satu masalah: textareatidak menyusut jika Anda menghapus konten. Saya tidak dapat menemukan cara untuk mengecilkannya ke ukuran yang benar - clientHeightnilainya kembali sebagai ukuran penuh textarea, bukan isinya.

Kode dari halaman itu di bawah ini:

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
sumber
Jawaban yang diterima untuk utas yang Anda tautkan berfungsi untuk saya. Menambahkan jeda baris memperluas textarea dan menghapusnya menyusut area teks. Browser apa yang Anda gunakan?
EndangeredMassa
3
Fungsi saya tidak salah. Anda harus mengetikkan baris baru di akhir baris. Ini solusi yang lebih baik. james.padolsey.com/javascript/jquery-plugin-autoresize
Anda dapat mencoba plugin saya untuk ini: github.com/AndrewDryga/jQuery.Textarea.Autoresize
Andrew Dryga
kemungkinan duplikat Autosizing textarea menggunakan prototipe
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
Saya membuat paket untuk ini jika Anda menggunakan reaksi: npmjs.com/package/react-fluid-textarea
Martin Dawson

Jawaban:

230

Ini berfungsi untuk saya (Firefox 3.6 / 4.0 dan 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>

Jika Anda ingin mencobanya di jsfiddle Ini dimulai dengan satu baris dan hanya tumbuh jumlah yang tepat yang diperlukan. Tidak apa-apa untuk satu textarea, tetapi saya ingin menulis sesuatu di mana saya akan memiliki banyak begitu banyak textarea(sekitar sebanyak satu biasanya akan memiliki baris dalam dokumen teks besar). Dalam hal ini sangat lambat. (Di Firefox sangat lambat.) Jadi saya benar-benar ingin pendekatan yang menggunakan CSS murni. Ini mungkin dengan contenteditable, tapi saya ingin hanya teks biasa.

panzi
sumber
13
Itu benar! Membuat jsfiddle untuk Anda: jsfiddle.net/CbqFv Sekarang berfungsi di Chrome, Firefox, dan IE8 - meskipun sedikit glitchy di IE8. Saat Anda menambah atau mengurangi jumlah garis, itu sedikit aneh. Seperti yang mungkin Anda lihat di plugin autoresize untuk jQuery, mereka mengatasinya dengan mengkloning textarea, mengatur ketinggiannya ke otomatis daripada yang asli, lalu menggunakannya untuk mengatur ketinggian scroll pada aslinya. Saya melakukan itu dalam biola yang diperbarui ini: jsfiddle.net/CbqFv/2 Ia memecahkan masalah IE tetapi Firefox berhenti berfungsi.
Chris Moschini
3
@HelenNeely: Kalau begitu jangan gunakan id. Misalnya, gunakan kelas dan lakukan apa yang init lakukan untuk semua elemen kelas itu. Itu harus menjadi tugas pemula.
panzi
3
@ DenilsonSá Jika seseorang hanya dapat berasumsi bahwa hanya browser modern yang digunakan web akan menjadi tempat yang lebih baik.
panzi
2
Ini tidak akan berfungsi dengan baik jika scrollbar dilibatkan di IE11. Jika Anda menggunakan jsfiddle.net/CbqFv biola ini dan masukkan baris sampai Anda memiliki bilah gulir, Anda akan melihatnya. Ada ide?
kaljak
6
Ini benar-benar rusak jika textarea dekat bagian bawah halaman - semuanya melompat mundur dan maju karena style.height='auto'. Saya menduga solusinya adalah dengan menambahkan saudara kandung tersembunyi yang hanya digunakan untuk pengukuran.
rr-
372

SOLUSI SIMPLE BELUM LENGKAP

Diperbarui 2020-05-14 (Dukungan browser yang ditingkatkan untuk ponsel dan tablet)

Kode berikut akan berfungsi:

  • Pada input kunci.
  • Dengan teks yang disisipkan (klik kanan & ctrl + v).
  • Dengan memotong teks (klik kanan & ctrl + x).
  • Dengan teks yang dimuat sebelumnya.
  • Dengan semua textarea (multiline textbox) lebar .
  • Dengan Firefox (v31-67 diuji).
  • Dengan Chrome (v37-74 diuji).
  • Dengan IE (v9-v11 diuji).
  • Dengan Edge (v14-v18 diuji).
  • Dengan IOS Safari .
  • Dengan Browser Android .
  • Dengan mode ketat JavaScript .
  • Apakah w3c divalidasi.
  • Dan efisien dan efisien.

OPSI 1 (Dengan jQuery)

Opsi ini membutuhkan jQuery dan telah diuji dan bekerja dengan 1.7.2 - 3.3.1

Sederhana (Tambahkan kode jquery ini ke file skrip master Anda dan lupakan tentang itu.)

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


OPSI 2 (JavaScript Murni)

Sederhana (Tambahkan JavaScript ini ke file skrip master Anda dan lupakan saja.)

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


OPSI 3 (Ekstensi jQuery)

Berguna jika Anda ingin menerapkan rangkaian lebih lanjut ke area teks yang Anda inginkan berukuran otomatis.

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

Ajak dengan $('textarea').autoHeight()


MEMPERBARUI TEXTAREA MELALUI JAVASCRIPT

Saat menyuntikkan konten ke dalam textarea melalui JavaScript, tambahkan kode berikut untuk menjalankan fungsi di opsi 1.

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

PRESET TEXTAREA HEIGHT

Untuk memperbaiki ketinggian awal teks Anda perlu menambahkan kondisi tambahan:

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
sumber
12
Ini adalah solusi yang bagus, itu akan sedikit lebih dimengerti jika nama metode dan nama parameter diperbarui menjadi nama sebenarnya daripada huruf individual.
Chris Marisic
5
@Obsidian, Terima kasih! Saya baru tahu mengapa saya selalu mendapatkan 0 —— Saya meletakkan textarea di modal Bootstrap! Ketika modal disembunyikan pada awalnya, textarea di dalamnya akan memiliki 0 scrollHeight 😂😂
WTIFS
7
@Obsidian, Fantastis !! (Opsi 3). Ini this.style.height = 'auto';adalah memperbaiki perilaku ajaib. Saya sangat frustrasi mengapa scrollHeight sangat aneh dalam perilaku. Ketinggian ke otomatis, kemudian mencocokkan scrollHeight dalam siklus render yang sama masih meniup pikiran saya bagaimana itu 'memperbaiki' masalah ini meskipun seharusnya hanya secara teknis mengecat ketinggian kedua.
bit-less
2
Saya mencoba opsi 3 di Chrome hari ini dan harus melakukan beberapa penyesuaian. 1) Ini tidak akan selalu mengubah ukuran dengan benar jika Anda memiliki transisi "tinggi" atau "semua" pada textarea. Saya sarankan tidak menggunakan transisi yang mempengaruhi ketinggian. 2) ScrollHeight mengembalikan setinggi dua baris (mungkin karena itu adalah default untuk textareas di Chrome) tetapi jika Anda mengubah this.style.height = 'auto'; ke this.style.height = '0px'; dan tambahkan min-height untuk mencegah keadaan awal dari benar-benar pergi ke 0, scrollHeight akan dengan benar mengembalikan satu baris tinggi bila diperlukan.
ZorroDeLaArena
3
@Obsidian Bisakah Anda menjelaskan bagaimana cara this.style.height = 'auto';memperbaiki perilaku scrollHeight? Itu hanya sihir.
sidney
63

Solusi jQuery menyesuaikan css agar sesuai dengan kebutuhan Anda

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

ATAU alternatif untuk jQuery 1.7 + ...

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

Saya telah membuat biola dengan gaya minimum absolut sebagai titik awal untuk percobaan Anda ... http://jsfiddle.net/53eAy/951/

chim
sumber
5
Ini bagus, tapi saya akan menambahkan overflow-y: hidden;ke css untuk mencegah bilah gulir berkedip sebentar ketika mengubah ukuran terjadi.
brettjonesdev
Tidak sepenuhnya yakin, tetapi tanpa itu area teks tumbuh terlalu banyak. Saya pikir ini ada hubungannya dengan cara elemen scrollHeight dihitung.
chim
1
Gunakan beberapa acara untuk membuat skenario yang lebih baik $('textarea.auto-resize').on('change cut paste drop keyup', function(){...})
raxith
1
Melompat seperti orang gila di Chrome 40 Win 8.1 pada teks lebih panjang dari viewport. Membuatnya tidak bisa digunakan.
tobibeer
1
Memegang enter (baris baru) menghasilkan scrolling. Ukuran tidak menyesuaikan sampai kunci dilepaskan.
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>

Diuji di Firefox 14 dan Chromium 18. Angka 24 dan 12 adalah arbitrer, uji untuk melihat apa yang paling cocok untuk Anda.

Anda bisa melakukannya tanpa tag gaya dan skrip, tetapi itu menjadi imho yang sedikit berantakan (ini adalah gaya lama HTML + JS dan tidak dianjurkan).

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

Edit: kode yang dimodernisasi. Atribut onkeyup yang diubah menjadi addEventListener.
Edit: keydown bekerja lebih baik daripada keyup
Edit: mendeklarasikan fungsi sebelum menggunakan
Edit: input bekerja lebih baik daripada keydown (thnx @ WASD42 & @ MA-Maddin)

jsfiddle

GijsjanB
sumber
3
Yang ini memiliki beberapa kelemahan: 1) Textarea tidak akan diubah ukurannya maka pengguna menempelkan sesuatu hanya dengan tombol mouse-nya; 2) Jika pengguna akan menempelkan sesuatu menggunakan keyboard (Ctrl + V) textarea akan diubah ukurannya hanya ketika ia akan melepaskan Ctrl. Jika pengguna akan menekan Ctrl + V beberapa kali maka textarea akan tumbuh hanya setelah yang terakhir. Anda harus menambahkan fungsi yang sama untuk menempel, memotong, mengubah, dan menjatuhkan acara juga.
WASD42
Jadi gunakan saja inputacara itu. Lihat stackoverflow.com/a/14029861/1951524
Martin Schneider
Versi yang disempurnakan dengan beberapa textareadukungan sebagai satu-liner:document.querySelectorAll('textarea').forEach(function(te){ te.addEventListener("input", function() { this.style.height='24px'; this.style.height=this.scrollHeight+12+'px'; }); });
Meisner
1
@ Meisner Lebih pendek, tapi saya tidak mengatakan itu "ditingkatkan". Dengan fungsi anonim, tidak ada cara untuk memanggil removeEventListenerdan membersihkan pendengar acara Anda. Ini sangat penting saat membuat pendengar acara di semua tempat dalam loop forEach. Plus, dalam pandangan saya, keterbacaan jauh lebih penting daripada keringkasan.
GijsjanB
untuk orang lain dan masa depan saya, pastikan bahwa box-sizing: border-box;properti diatur atau yang lain textarea explands sebesar 4px untuk setiap acara onput. Saya menghabiskan waktu 3 jam sampai saya tahu ini masalahnya.
AIon
24

Solusi terbaik (berfungsi dan singkat) bagi saya adalah:

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

Ini bekerja seperti pesona tanpa berkedip dengan pasta (dengan mouse juga), memotong, masuk dan menyusut ke ukuran yang tepat.

Silakan lihat di jsFiddle .

vatavale
sumber
Hebat!!! kesepakatan satu baris! pertanyaan konyol, bisakah saya dapat menambahkan animasi ketika ukurannya diubah? seperti kotak teks agak mengubah ukuran perlahan daripada melompat ke ukuran?
user2513846
1
@ user2513846 Sepertinya tidak mungkin dengan desain multi-line editing. Saya membuat contoh animasi ukuran teks: jsfiddle.net/yk2g333e Seperti yang Anda tahu kursor teks turun pada dan dari garis atau tanda sisipan, jadi jika tidak ada jeda pada saat ini tidak ada yang menghidupkan. Tetapi menjeda akan mengganggu pengguna.
vatavale
1
@ user2513846 Namun, dengan satu lagi baris kosong di akhir textarea, dimungkinkan untuk memiliki animasi yang lancar: jsfiddle.net/p23erdfr
vatavale
16

Anda menggunakan nilai yang lebih tinggi dari clientHeight saat ini dan konten scrollHeight. Saat Anda membuat scrollHeight lebih kecil dengan menghapus konten, area yang dihitung tidak bisa menjadi lebih kecil karena clientHeight, yang sebelumnya ditetapkan oleh style.height, menahannya. Sebagai gantinya Anda dapat mengambil maks () dari scrollHeight dan nilai ketinggian minimum yang telah Anda tentukan atau hitung dari textarea.rows.

Secara umum Anda mungkin tidak harus benar-benar mengandalkan scrollHeight pada kontrol formulir. Terlepas dari scrollHeight yang secara tradisional kurang didukung secara luas daripada beberapa ekstensi IE lainnya, HTML / CSS tidak mengatakan apa-apa tentang bagaimana kontrol formulir diimplementasikan secara internal dan Anda tidak dijamin scrollHeight akan menjadi sesuatu yang bermakna. (Secara tradisional beberapa browser telah menggunakan widget OS untuk tugas tersebut, membuat interaksi CSS dan DOM pada internal mereka menjadi tidak mungkin.) Setidaknya mengendus untuk scrollHeight / clientHeight keberadaan sebelum mencoba untuk mengaktifkan efek.

Alternatif pendekatan lain yang mungkin untuk menghindari masalah ini jika penting bahwa ia bekerja lebih luas mungkin dengan menggunakan div tersembunyi yang berukuran sama lebar dengan textarea, dan atur dalam font yang sama. Pada keyup, Anda menyalin teks dari textarea ke node teks dalam div tersembunyi (ingat untuk mengganti '\ n' dengan jeda baris, dan keluar '<' / '&' dengan benar jika Anda menggunakan innerHTML). Maka cukup mengukur offset div. Tinggi akan memberi Anda ketinggian yang Anda butuhkan.

bobince
sumber
1
Browser mana yang seharusnya memiliki masalah dengan scrollHeightuntuk textareas? Bekerja dengan baik dengan versi IE, Firefox dan Opera saat ini ...
Christoph
1
Satu-satunya yang harus saya tangani adalah Konqueror, yang mengembalikan clientHeight sebagai scrollHeight. Ini adalah perilaku yang dapat Anda harapkan kecuali browser menerapkan model kotak CSS ke internal widget, sesuatu yang tidak selalu mereka lakukan dan standar tidak mengatakan mereka harus melakukannya.
bobince
14

Jika Anda tidak perlu mendukung IE8 Anda dapat menggunakan inputacara ini:

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

Sekarang Anda hanya perlu menambahkan beberapa CSS dan Anda selesai:

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

Pemakaian:

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

Anda dapat membaca lebih lanjut tentang cara kerjanya di posting blog saya .

Maximilian Hoffmann
sumber
1
Solusi yang bagus, tetapi perlu sedikit perbaikan. Ketika konten textarea dimuat f.ex. dari database, textarea tetap kecil. Anda harus memicu inputacara selama inisialisasi dalam siklus foreach.
Ajax
11

ukuran Otomatis

https://github.com/jackmoore/autosize

Hanya bekerja, mandiri, populer (3.0k + GitHub bintang per Oktober 2018), tersedia di cdnjs ) dan ringan (~ 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, jika Anda menggunakan ACE editor, gunakan maxLines: Infinity: Secara otomatis menyesuaikan ketinggian ke konten di Ace Cloud 9 editor

Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
sumber
2
Versi 2 telah dirilis pada Februari 2015. Ini menjadi lebih sederhana dan tidak bergantung pada jQuery lagi
crispy
Maaf, ini berhasil. Mungkin saya berada di browser lain .. jadi, saya pikir lebih baik jika Anda mengabaikan komentar saya ..
Toni Michel Caubet
@ToniMichelCaubet ah, OK mungkin masalah CDN kalau begitu. Biarkan saya periksa.
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
The autosizePlugin tidak memungkinkan untuk secara manual mengubah ukuran menggunakan ikon resize di textarea.
j4v1
7

Menemukan satu liner dari sini ;

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

Adakah yang menganggap konten dapat diedit? Tidak main-main dengan menggulir, dan satu-satunya JS yang saya suka tentang itu adalah jika Anda berencana untuk menyimpan data pada blur ... dan tampaknya, itu kompatibel pada semua browser populer: http://caniuse.com/#feat = dapat diedit

Cukup beri gaya agar terlihat seperti kotak teks, dan otomatis ... Jadikan min-height-nya tinggi teks yang disukai dan miliki.

Apa yang keren tentang pendekatan ini adalah Anda dapat menyimpan dan memberi tag pada beberapa browser.

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
sumber
Chrome akan menambahkan elemen <div> pada ENTER.
sbaechler
contenteditableitu bagus, tetapi jika Anda ingin plaintext itu membutuhkan banyak opsi seperti -webkit-user-modify: read-write-plaintext-onlydan white-space: pre-wrap.
mik01aj
@_sbaechler: <div> s dihilangkan saat menggunakan [dom-element].innerText. @WebmasterG IMHO akan lebih baik untuk menghilangkan jquery (untuk transparansi) dan untuk memasukkan contoh di halaman ini melalui Cuplikan Kode runnable alih-alih pada jsfiddle.
adabru
4

Saya menggunakan kode berikut untuk beberapa textareas. Bekerja dengan baik di Chrome 12, Firefox 5 dan IE 9, bahkan dengan tindakan hapus, potong, dan tempel yang dilakukan di textareas.

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

Ada pendekatan yang sedikit berbeda.

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

Idenya adalah untuk menyalin teks dari textareadalampre dan biarkan CSS memastikan bahwa mereka memiliki ukuran yang sama.

Manfaatnya adalah kerangka kerja menghadirkan alat sederhana untuk memindahkan teks tanpa menyentuh peristiwa apa pun. Yaitu, di AngularJS Anda akan menambahkan ng-model="foo" ng-trim="false"ke textareadan ng-bind="foo + '\n'"ke pre. Lihat biola .

Pastikan yang prememiliki ukuran font yang sama dengan textarea.

Karolis Juodelė
sumber
1
" Pastikan saja prememiliki ukuran font yang sama dengantextarea " - Mereka membutuhkan yang sama line-height, dan jumlah yang sama paddingdan / atau borderjuga. Ini adalah solusi terbaik untuk Angular.
Jamie Barker
4

Berikut ini berfungsi untuk memotong, menempel, dll., Terlepas dari apakah tindakan itu dari mouse, pintasan keyboard, memilih opsi dari bilah menu ... beberapa jawaban menggunakan pendekatan yang sama tetapi mereka tidak memperhitungkan kotak- ukuran, itulah sebabnya mereka salah menerapkan gaya overflow: hidden .

Saya melakukan hal berikut, yang juga berfungsi baik dengan max-heightdan rowsuntuk ketinggian minimum dan maksimum.

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>

Untuk kelengkapan absolut, Anda harus memanggil adjustfungsi dalam beberapa keadaan lagi:

  1. Ukuran jendela peristiwa, jika lebar textareaperubahan dengan ukuran jendela, atau peristiwa lain yang mengubah lebar teks
  2. Ketika textarea's displaygaya perubahan atribut, misalnya ketika pergi dari none(tersembunyi) keblock
  3. Ketika nilai textareadiubah secara terprogram

Perhatikan bahwa menggunakan window.getComputedStyleatau mendapatkan currentStylebisa agak mahal secara komputasi, jadi Anda mungkin ingin men-cache hasilnya.

Bekerja untuk IE6, jadi saya sangat berharap itu dukungan yang cukup baik.

Joseph Nields
sumber
4

Sebagai pendekatan yang berbeda, Anda dapat menggunakan <span>yang menyesuaikan ukurannya secara otomatis. Anda harus membuatnya dapat diedit dengan menambahkan contenteditable="true"properti dan Anda selesai:

div {
  width: 200px;
}

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

Satu-satunya masalah dengan pendekatan ini adalah jika Anda ingin mengirimkan nilai sebagai bagian dari formulir, Anda harus melakukannya sendiri di JavaScript. Melakukannya relatif mudah. Misalnya, Anda bisa menambahkan bidang tersembunyi dan dalam onsubmithal formulir menetapkan nilai spanbidang yang tersembunyi yang kemudian akan secara otomatis dikirimkan bersama formulir.

Racil Hilan
sumber
Sudah ada jawaban menggunakan contenteditable di halaman ini: stackoverflow.com/questions/454202/…
adabru
@ Adabru Ya, tetapi kedua jawabannya tidak sama. Toyota membuat mobil merah, dan Ford juga membuat mobil merah, tetapi mereka berbeda, bukan? Jika Anda lebih menyukai jawaban yang lain, maka ikutilah. Tetapi ada orang-orang yang lebih menghargai jawaban saya dan mengikutinya. Memiliki opsi yang berbeda itu baik.
Racil Hilan
3

Sedikit koreksi. Bekerja dengan sempurna di 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;
  });
artnik-pro
sumber
berfungsi selama garis Anda tidak meluap - maka itu tidak akan cocok.
Tomáš Kafka
bekerja di luar kotak, hebat (firefox 72)
Mikeys4u
2

Saya tahu cara yang singkat dan benar untuk mengimplementasikan ini dengan jquery. Tidak diperlukan div tambahan yang tersembunyi dan berfungsi di sebagian besar browser

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

sumber
jQuery .live()sudah tidak digunakan lagi. api.jquery.com/live Biasanya Anda ingin menggunakannya .on().
Lukas
2

Saya tidak tahu apakah ada yang menyebutkan cara ini tetapi dalam beberapa kasus dimungkinkan untuk mengubah ukuran ketinggian dengan baris Atribut

textarea.setAttribute('rows',breaks);

Demo

h0mayun
sumber
1
Itu hanya berfungsi jika Anda punya white-space: nowrap;. Ketika sebuah baris membungkus ke baris lain tanpa putus baris, textarea tidak akan disesuaikan dengan benar lagi.
Yeti
2

Berikut adalah arahan sudut untuk jawaban 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
sumber
Anda sebaiknya menggunakan $ timeout daripada setTimout - ini akan memastikan bahwa model diinisialisasi (tidak perlu menentukan milidetik - itu akan dieksekusi setelah siklus intisari Angular). Juga elemen = elemen [0]; adalah praktik yang sangat buruk ... Bagaimanapun, solusinya tidak baik bagi saya karena saya perlu textarea menjadi satu baris sampai ada lebih banyak teks.
Karol Websky
2

Anda dapat menggunakan JQuery untuk memperluas textareasaat mengetik:

$(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
sumber
Solusi terbersih. tetapi karena kita harus berhenti menggunakan jQuery: textarea.addEventListener ('keyup', () => {textarea.style.height = 0; textarea.style.height = ${textarea.scrollHeight}px;});
Toni Michel Caubet
2

Mereka yang ingin mencapai hal yang sama di versi baru Angular.

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

Saya juga menambahkan use case lain yang mungkin berguna bagi beberapa pengguna yang membaca utas, ketika pengguna ingin meningkatkan ketinggian area teks ke ketinggian tertentu dan kemudian menggunakannya overflow:scroll, metode di atas dapat diperluas untuk mencapai use-case yang disebutkan.

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

Beberapa jawaban di sini tidak memperhitungkan bantalan.

Dengan asumsi Anda memiliki maxHeight yang tidak ingin Anda kunjungi, ini bekerja untuk saya:

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

Pendekatan yang lebih sederhana dan lebih bersih adalah ini:

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

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

Yang diperlukan hanyalah menambahkan .auto-heightkelas ke apa pun textareayang ingin Anda targetkan.

Diuji dalam FF, Chrome dan Safari. Beri tahu saya jika ini tidak berhasil untuk Anda, karena alasan apa pun. Tapi, ini adalah cara paling bersih dan paling sederhana yang saya temukan ini berfungsi. Dan itu berhasil! : D

menghidupkan kembali
sumber
Apakah Anda mencoba menghapus teks setelah diedit? Apakah teksnya runtuh?
18C
1

Kode ini berfungsi untuk menempel dan memilih hapus juga.

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>

Ini JSFiddle

Kurenai Kunai
sumber
1

Saya merekomendasikan perpustakaan javascript dari http://javierjulio.github.io/textarea-autosize .

Per komentar, tambahkan contoh kode kunci pada penggunaan plugin:

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

Minimum CSS yang dibutuhkan:

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

MakeTextAreaResisable yang menggunakan 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 Krupitsky
sumber
1

Tampaknya tidak ada jawaban yang berhasil. Tapi yang ini berfungsi untuk saya: 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
sumber
Ini harus menjadi jawaban yang diterima, meskipun itu cukup untuk mendengarkan acara "keyup"
Bob Ross
1

implementasi saya sangat sederhana, hitung jumlah baris dalam input (dan minimum 2 baris untuk menunjukkan bahwa itu adalah textarea):

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

contoh kerja penuh dengan stimulus: https://jsbin.com/kajosolini/1/edit?html,js,output

(dan ini bekerja dengan pegangan ukuran manual manual misalnya)

localhostdotdev
sumber
2
Ini hanya berfungsi jika Anda melanggar garis dengan menekan "enter". Jika teks Anda lebih panjang dari lebar textarea tetapi Anda tidak menekan "enter", itu tidak berkembang.
Nathalia Xavier
1

Jawaban yang diterima bekerja dengan baik. Tapi itu banyak kode untuk fungsi sederhana ini. Kode di bawah ini akan melakukan triknya.

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

Inilah yang saya lakukan saat menggunakan MVC HTML Helper untuk TextArea. Saya memiliki beberapa elemen textarea sehingga harus membedakan mereka menggunakan Model Id.

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

dan dalam skrip menambahkan ini:

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

Saya telah mengujinya di IE10 dan Firefox23

Gunnerz
sumber
0

Anda dapat menggunakan kode ini:

Naskah:

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
sumber