Створення текстової області з автоматичним розміром


366

Про це була ще одна нитка , яку я спробував. Але є одна проблема: textareaвона не зменшується, якщо видалити вміст. Я не можу знайти спосіб зменшити його до потрібного розміру - clientHeightзначення повертається як повний розмір textarea, а не його вміст.

Код із цієї сторінки знаходиться нижче:

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

Прийнята відповідь для теми, яку ви пов’язали, працює для мене. Додавання розривів рядків розширює текстову область і видалення їх скорочує область тексту. Який браузер ви використовуєте?
EndangeredMassa

3
Моя функція робить помилку. Обов’язково вводити новий рядок в кінці рядка. Це краще рішення. james.padolsey.com/javascript/jquery-plugin-autoresize

Ви можете спробувати мій плагін для цього: github.com/AndrewDryga/jQuery.Textarea.Autoresize
Андрій Дрига


Я створив пакет для цього, якщо ви використовуєте reakct
Мартін Доусон

Відповіді:


230

Це працює для мене (Firefox 3.6 / 4.0 та 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>

Якщо ви хочете спробувати його на jsfiddle, він починається з одного рядка і вирощує лише необхідну кількість. Це добре для одного textarea, але я хотів написати щось там, де я мав би багато-багато таких textareas (приблизно стільки, скільки в одному текстовому документі зазвичай було б рядків). У цьому випадку це дуже повільно. (У Firefox це шалено повільно.) Тому я дуже хотів би підхід, який використовує чистий CSS. Це було б можливо contenteditable, але я хочу, щоб це було лише в простому тексті.


13
Це робить! Створив jsfiddle для ya: jsfiddle.net/CbqFv Зараз він працює в Chrome, Firefox та IE8 - хоча це трохи глючно в IE8. Зі збільшенням чи зменшенням кількості рядків це трохи вироджується. Як ви могли бачити у плагіні автоматичного розміру для jQuery, вони обходять це, клонуючи текстову область, встановлюючи її висоту на автоматичну замість оригіналу, а потім використовують її для встановлення висоти прокрутки на оригінал. Я зробив це в цій оновленій скрипці: jsfiddle.net/CbqFv/2 Він вирішує проблему IE, але Firefox перестає працювати.
Кріс Москіні

3
@HelenNeely: Тоді не використовуйте ідентифікатор. Наприклад, використовуйте клас і робіть те, що робить init для всіх елементів цього класу. Це повинно бути завданням для початківців.
панци

3
@ DenilsonSá Якби можна було тільки припустити, що використовуються лише сучасні браузери, веб було б кращим.
панци

2
Це не спрацює, якщо смуга прокрутки включена в IE11. Якщо ви використовуєте цю скрипку jsfiddle.net/CbqFv і вводите рядки, поки не отримаєте смугу прокрутки, ви побачите її. Будь-які ідеї?
калак

6
Це повністю розривається, якщо текстова область знаходиться внизу кінця сторінки - все скаче вперед і вперед через style.height='auto'. Я підозрюю, що рішення полягає в тому, щоб додати прихований брат, який використовується тільки для вимірювання.
rr-

372

ЦІЛЬКИЙ ПРОСТИЙ РІШЕННЯ

Оновлено 2020-05-14 (покращена підтримка браузера для мобільних телефонів та планшетів)

Наступний код буде працювати:

  • При введенні ключа.
  • З вставленим текстом (клацніть правою кнопкою миші та ctrl + v).
  • З вирізаним текстом (клацніть правою кнопкою миші та ctrl + x).
  • З попередньо завантаженим текстом.
  • З усім сайтом textarea (багаторядковий текстовий текст ) .
  • За допомогою Firefox (перевірено v31-67).
  • З Chrome (перевірено v37-74).
  • З IE (випробувано v9-v11).
  • З Edge (перевірено v14-v18).
  • З IOS Safari .
  • За допомогою браузера Android .
  • З суворим режимом JavaScript .
  • Чи підтверджено w3c .
  • Він є оптимізованим та ефективним.

ВАРІАНТ 1 (З jQuery)

Цей параметр вимагає jQuery і був протестований і працює з 1.7.2 - 3.3.1

Простий (Додайте цей код jquery до файлу головного сценарію та забудьте про нього.)

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


ВАРІАНТ 2 (чистий JavaScript)

Просто (Додайте цей JavaScript у свій файл головного сценарію та забудьте про нього.)

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


ВАРІАНТ 3 (Розширення jQuery)

Корисно, якщо ви хочете застосувати додаткове прив’язування до текстових областей, які ви хочете мати автоматичний розмір.

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

Викликати с $('textarea').autoHeight()


ОНОВЛЕННЯ TEXTAREA VIA JAVASCRIPT

Під час введення вмісту в текстову область через JavaScript додайте наступний код, щоб викликати функцію у варіанті 1.

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

ПРЕСЕТ ТЕКСТАРЕЯ ВИСОКА

Щоб зафіксувати початкову висоту текстової області, потрібно буде додати додаткову умову:

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
Це чудове рішення, було б трохи зрозуміліше, якби ім'я методу та ім'я параметра були оновлені на справжні імена замість окремих літер.
Кріс Марісіч

5
@Obsidian Дякую! Я просто зрозумів, чому я завжди отримую 0 - я помістив textarea в режим Bootstrap! Оскільки модал прихований спочатку, текстові області в ньому матимуть 0 прокруткиВисота 😂😂
WTIFS

7
@Obsidian Fantastic !! (Варіант 3). Це this.style.height = 'auto';виправлення магічної поведінки. Мене так засмутило, чому прокруткаВисота була такою дивною у поведінці. Висота автоматично, а потім відповідність scrollHeight у тому самому циклі візуалізації все ще підштовхує мою думку про те, як вона «виправляє» цю проблему, хоча це має бути лише технічно фарбувати другу висоту.
трохи менше

2
Я спробував варіант 3 в Chrome сьогодні і мені довелося зробити кілька перетворень. 1) Не завжди буде змінено правильний розмір вниз, якщо у вас є перехід "висота" або "все" на текстовій області. Я б рекомендував не використовувати переходи, що впливають на висоту. 2) ScrollHeight повертає мінімум у два ряди, що мають висоту (можливо, тому, що це текстові області в Chrome за замовчуванням), але якщо ви змінили this.style.height = 'auto'; до цього.style.height = '0px'; і додайте мінімальну висоту, щоб запобігти фактичному переходу початкового стану до 0, scrollHeight правильно поверне один ряд висоти, коли це доречно.
ZorroDeLaArena

3
@Obsidian Чи можете ви пояснити, як this.style.height = 'auto';виправляє поведінку scrollHeight? Це просто магія.
sidney

63

Рішення jQuery налаштуйте css відповідно до ваших вимог

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

АБО альтернатива jQuery 1.7 + ...

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

Я створив загадку з абсолютним мінімальним стилем як вихідну точку для ваших експериментів ... http://jsfiddle.net/53eAy/951/


5
Це добре, але я б додав overflow-y: hidden;до css, щоб запобігти ненадовго блимати смузі прокрутки, коли настає розмір.
brettjonesdev

Не зовсім впевнений, але без цього область тексту занадто сильно зростає. Я думаю, це пов'язано з тим, як обчислюються елементи прокручування висоти.
шим

1
Використовуйте кілька подій, щоб зробити роботу для широкої правдивості сценарію $('textarea.auto-resize').on('change cut paste drop keyup', function(){...})
raxith

1
Стрибки, як божевільні, в Chrome 40 Win 8.1 на текстах, довших за вікно перегляду. Це робить його зовсім непридатним.
tobibeer

1
Утримуючи клавішу введення (нова лінія) призводить до прокрутки. Розмір не регулюється доти, доки не буде відпущено ключ.
Нільс Абілдгаард

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 та Chromium 18. Числа 24 та 12 є довільними, перевіряйте, що вам найбільше підходить.

Можна обійтися без тегів стилів та сценаріїв, але це стає трохи безладним імхо (це старий HTML + JS стиль і не рекомендується).

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

Правка: модернізований код. Змінено атрибут onkeyup для addEventListener.
Редагувати: клавіатура працює краще, ніж клавіатура.
Редагувати: оголосити функцію перед використанням
Правка: введення працює краще, ніж клавішне (thnx @ WASD42 та @ MA-Maddin)

jsfiddle


3
У цього є деякі недоліки: 1) Textarea не змінюється, тоді користувач вставляє щось лише за допомогою кнопок миші; 2) Якщо користувач вставить щось за допомогою клавіатури (Ctrl + V), текстову область буде змінено лише тоді, коли він випустить Ctrl. Якщо користувач кілька разів натисне Ctrl + V, текстова область зростатиме лише після останнього. Ви також повинні додати ту саму функцію, щоб також вставляти, вирізати, змінювати та видаляти події.
WASD42

Тому просто використовуйте inputподію замість цього. Дивіться stackoverflow.com/a/14029861/1951524
Мартін Шнайдер

Вдосконалена версія з багаторазовою textareaпідтримкою як однолінійний:document.querySelectorAll('textarea').forEach(function(te){ te.addEventListener("input", function() { this.style.height='24px'; this.style.height=this.scrollHeight+12+'px'; }); });
Meisner

1
@Meisner Це коротше, але я б не сказав, що це "покращено". Завдяки анонімній функції немає можливості зателефонувати removeEventListenerта очистити слухачів подій. Це особливо важливо при створенні слухачів подій в усьому циклі forEach. Плюс, на мій погляд, читабельність набагато важливіша, ніж стислість.
GijsjanB

для інших та майбутніх мене переконайтеся, що встановлено box-sizing: border-box;властивість, або ж textarea пояснює 4px для кожного події OnInput. Я витратив, як 3 години, поки я не зрозумів, що це проблема.
AIon

24

Найкраще рішення (працює і коротко) для мене:

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

Це працює як шарм, не маргаючи пастою (також мишкою), вирізати, вводити і скорочується до потрібного розміру.

Погляньте, будь ласка, на jsFiddle .


Страхітливий !!! одна лінія угоди! дурне питання хо я можу додати анімацію, коли вона змінить розмір? як, наприклад, текстове поле сорта м'яко змінює розмір, а не стрибок до розміру?
користувач2513846

1
@ user2513846 Схоже, це неможливо завдяки дизайну багаторядкових редагувань. Я зробив приклад анімації розміру текстової області: jsfiddle.net/yk2g333e Як ви знаєте, текстовий курсор опускається в рядку або рядку або кареті, тому, якщо в цей момент немає пауз, анімувати немає чого. Але пауза буде дратувати користувачів.
vatavale

1
@ user2513846 Однак з ще одним порожнім рядком в кінці текстової області можлива плавна анімація: jsfiddle.net/p23erdfr
vatavale

16

Ви використовуєте більш високе значення поточного clientHeight та вмісту scrollHeight. Коли ви зробите scrollHeight, видаляючи вміст, обчислена площа не може зменшитися, тому що clientHeight, раніше встановлений style.height, тримає її відкритою. Ви можете замість цього взяти макс () з scrollHeight та мінімальне значення висоти, яке ви задали або обчислили з textarea.row.

Як правило, ви, мабуть, не повинні покладатися на scrollHeight на елементи управління формами. Крім того, що scrollHeight є традиційно менш широко підтримуваним, ніж деякі інші розширення IE, HTML / CSS нічого не говорить про те, як управління формами реалізується внутрішньо, і ви не гарантуєте, що scrollHeight буде нічого значимого. (Традиційно деякі браузери використовують віджети ОС для виконання завдання, що робить взаємодію CSS та DOM у внутрішніх умовах неможливою.) Принаймні, нюхайте за існування scrollHeight / clientHeight, перш ніж намагатися ввімкнути ефект.

Іншим можливим альтернативним підходом, щоб уникнути проблеми, якщо важливо, щоб він працював ширше, може бути використання прихованого поділу розміром з тією ж шириною, що і текстові області, та встановлення того ж шрифту. При клавіатурі ви копіюєте текст з текстової області в текстовий вузол у прихованому розділі (пам'ятаючи, що замініть '\ n' на розрив рядка, і вимкніть '<' / '&' належним чином, якщо ви використовуєте innerHTML). Тоді просто вимірявши зміщення дива. Висота дасть вам потрібну вам висоту.


1
Які браузери, як передбачається, мають проблеми з scrollHeightтекстовими версіями? Чудово працює з поточними версіями IE, Firefox та Opera ...
Крістоф

1
Єдиний, що мені потрібно подати, це Konqueror, який повертає clientHeight як scrollHeight. Такої поведінки можна очікувати, якщо браузер не застосує модель вікна CSS до внутрішніх програм віджетів, чого вони не завжди робили, і стандарт не говорить про те, що вони повинні робити.
bobince

14

Якщо вам не потрібно підтримувати IE8, ви можете використовувати inputподію:

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

Тепер вам потрібно лише додати трохи CSS, і ви закінчите:

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

Використання:

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

Детальніше про те, як це працює, ви можете прочитати в моїй публікації в блозі .


1
Приємне рішення, але потрібно трохи виправити. Коли вміст textarea завантажується f.ex. З бази даних текстові області залишаються невеликими. Ви повинні запустити inputподію під час ініціалізації в циклі foreach.
Аякс

11

автоматизувати

https://github.com/jackmoore/autosize

Просто працює, автономний, популярний (3,0k + зірки GitHub станом на жовтень 2018), доступний на cdnjs ) та легкий (~ 3,5 к). Демонстрація:

<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, використовуйте maxLines: Infinity: Автоматично регулюйте висоту вмісту в редакторі Ace Cloud 9


2
Версія 2 була випущена в лютому 2015 року. Вона стала простішою і вже не залежить від jQuery
хрусткий

Вибачте, це працює. Можливо, я був у іншому браузері .. тож, я думаю, що краще, якщо ви проігноруєте мій коментар ..
Тоні Мішель Каубе

@ToniMichelCaubet ах, добре, можливо, проблема з CDN тоді. Дай мені перевірити.
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

autosizeПлагін не дозволяє вручну змінити розмір , використовуючи значок зміни розміру в текстовому полі.
j4v1

7

Знайшов один лайнер звідси ;

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

6

Хтось вважав суперечливим? Ні з ким не возитися з прокруткою, єдиний JS, який мені подобається, це якщо ви плануєте зберегти дані на розмиті ... і, мабуть, він сумісний у всіх популярних браузерах: http://caniuse.com/#feat = зміст

Просто накресліть його так, щоб він виглядав як текстове поле, і він автоматично розміщується ... Зробіть його мінімальною висотою бажаною висотою тексту та мати її.

Що в цьому підході - це те, що ви можете зберігати та розміщувати теги на деяких браузерах.

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 додасть <div> елементів у поле ENTER.
sbaechler

contenteditableце добре, але якщо ви хочете в простому тексті, йому потрібна купа варіантів, як -webkit-user-modify: read-write-plaintext-onlyі white-space: pre-wrap.
mik01aj

@_sbaechler: <div> s опускати під час використання [dom-element].innerText. @WebmasterG IMHO було б непогано опустити jquery (для прозорості) та включити приклад на цю сторінку за допомогою виконуваного фрагменту коду замість jsfiddle.
адабр

4

Я використовував наступний код для декількох текстових областей. Добре працює в Chrome 12, Firefox 5 та IE 9, навіть із видаленням, вирізанням та вставкою дій, виконаних у текстових областях.

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

Існує дещо інший підхід.

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

Ідея полягає в тому, щоб скопіювати текст із textareaфайлу в preCSS і переконатися, що вони мають однаковий розмір.

Перевага полягає в тому, що рамки представляють прості інструменти для переміщення тексту, не торкаючись жодних подій. А саме, в AngularJS ви б додати ng-model="foo" ng-trim="false"до textareaі ng-bind="foo + '\n'"до pre. Дивіться загадку .

Просто переконайтеся, що preрозмір шрифту має такий самий розмір, як і textarea.


1
Msgstrpretextarea " Просто переконайтеся, що розмір шрифту має такий самий розмір, як " - Їм потрібен line-heightоднаковий розмір paddingта / або borderзанадто. Це найкраще рішення для Angular.
Джеймі Баркер

4

Наступні роботи для вирізання, вставки та ін., Незалежно від того, чи є ці дії від миші, ярлика клавіатури, вибору параметра з панелі меню ... кілька відповідей застосовують аналогічний підхід, але вони не враховують вікно, розмір, тому вони неправильно застосовують стиль overflow: hidden.

Я роблю таке, що також добре працює з max-heightі 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>

Для абсолютної повноти ви повинні викликати adjustфункцію ще за кількох обставин:

  1. Події зміни розміру вікна, якщо ширина textareaзмін із зміною розміру вікна або інші події, що змінюють ширину текстової області
  2. Коли атрибут стилю textarea's displayзмінюється, наприклад, коли він переходить від none(прихованого) доblock
  3. Коли значення textareaзмінено програмно

Зауважте, що використання window.getComputedStyleабо отримання currentStyleможе бути дещо обчислювально дорогим, тому ви, можливо, захочете замість цього кешувати результат.

Працює для IE6, тому я дуже сподіваюся, що це досить хороша підтримка.


4

Як інший підхід, ви можете використовувати режим, <span>який автоматично регулює його розмір. Вам потрібно зробити його редагованим, додавши contenteditable="true"властивість, і ви закінчите:

div {
  width: 200px;
}

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

Єдине питання такого підходу полягає в тому, що якщо ви хочете подати значення як частину форми, вам доведеться це зробити самостійно в JavaScript. Зробити це порівняно просто. Наприклад, ви можете додати приховане поле і в onsubmitразі форми призначити значення spanприхованому полі, яке потім буде автоматично подано разом із формою.


Існує вже відповідь з допомогою contenteditable на цій сторінці: stackoverflow.com/questions/454202 / ...
adabru

@adabru Так, але дві відповіді неоднакові. Toyota робить червоні автомобілі, а Ford теж робить червоні автомобілі, але вони різні, чи не так? Якщо вам більше подобається інша відповідь, тоді продовжуйте її. Але є такі, хто більше цінує мою відповідь і йде з нею. Маючи різні варіанти - це добре.
Расіл Хілан

3

Трохи виправлень. Прекрасно працює в Опері

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

працює, поки ваші рядки не переповнюються - тоді вони не підходять.
Томаш Кафка

працює з коробки, великий (світлячок 72)
Mikeys4u

2

Я знаю короткий і правильний спосіб реалізації цього за допомогою jquery.Не потрібні додаткові приховані діви та працюють у більшості браузерів

<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()застаріло. api.jquery.com/live Зазвичай ви хочете використовувати .on()замість цього.
Лука

2

Я не знаю, чи хтось згадує такий спосіб, але в деяких випадках можливо змінити висоту за допомогою рядків Attribute

textarea.setAttribute('rows',breaks);

Демо


1
Це працює лише у вас white-space: nowrap;. Коли рядок переходить на інший рядок без розриву рядка, текстова область більше не буде відрегульована належним чином.
Йєті

2

Ось angularjs директива для відповіді 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>

Ви повинні скоріше використовувати $ timeout, ніж setTimout - це забезпечить ініціалізацію моделі (не потрібно вказувати мілісекунди - вона буде виконуватися після циклу дайджеста кута). Також елемент = елемент [0]; це дуже погана практика ... У будь-якому випадку рішення для мене не годиться, оскільки мені потрібно, щоб текстові області були однорядними, поки не буде більше тексту.
Кароль Вебський

2

Ви можете використовувати JQuery, щоб розширити textareaчас набору тексту:

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


Найчистіший розчин. але як слід припинити використання jQuery: textarea.addEventListener ('keyup', () => {textarea.style.height = 0; textarea.style.height = ${textarea.scrollHeight}px;});
Тоні Мішель Каубе

2

Тим, хто хоче досягти того ж у нових версіях Angular.

Захоплення текстуArea 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>

Я також додаю ще один випадок використання, який може стати в нагоді деяким користувачам, які читають нитку, коли користувач хоче збільшити висоту області тексту до певної висоти, а потім мати overflow:scrollна ній, вищевказаний метод можна розширити для досягнення згаданого випадку використання.

  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

Деякі відповіді тут не враховують прокладки.

Якщо припустити, що у вас є maxHeight, який ви не хочете переходити, це працювало для мене:

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

Ще простіший і чистіший підхід такий:

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

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

Все, що потрібно - це додати .auto-heightклас до будь-якого textareaви хочете націлити.

Тестували на FF, Chrome та Safari. Повідомте мене, якщо це не працює для вас з будь-якої причини. Але це найчистіший і найпростіший спосіб, коли я знайшов це для роботи. І це чудово працює! : D


Ви намагалися видалити текст після редагування? Чи руйнувалась текстарія?
18C

1

Цей код працює для вставки та вибору також видалити.

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>

Ось JSFiddle


1

Я рекомендую бібліотеку javascript від http://javierjulio.github.io/textarea-autosize .

За коментарями додайте приклад кодового блоку щодо використання плагінів:

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

Мінімально необхідний CSS:

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

1

MakeTextAreaResisable, що використовує 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();
}

1

Жодна з відповідей, здається, не працює. Але це для мене працює: 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();

Це має бути прийнятою відповіддю, хоча достатньо прослухати "клавішні" події
Боб Росс

1

моя реалізація дуже проста, порахуйте кількість рядків у введеному документі (і мінімум 2 рядки, щоб показати, що це textarea):

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

повний робочий приклад із стимулом: https://jsbin.com/kajosolini/1/edit?html,js,output

(і це працює, наприклад, з ручною ручкою зміни розміру)


2
Це працює лише в тому випадку, якщо ви перервите рядок, натиснувши "ввести". Якщо текст більше, ніж ширина текстової області, але ви не натискаєте "ввести", він не розширюється.
Наталія Ксав’є

1

Прийнята відповідь справно працює. Але це дуже багато коду для цього простого функціоналу. Наведений нижче код зробить трюк.

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

0

Ось що я зробив, використовуючи MVC HTML Helper для TextArea. У мене було досить багато елементів textarea, тому довелося розрізнити їх за допомогою Model Id.

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

і в скрипті додав це:

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

Я перевірив його на IE10 та Firefox23


0

Ви можете використовувати цей код:

Кафедра:

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();
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.