Создание текстовой области с автоматическим изменением размера


367

Был еще один поток об этом , который я попробовал. Но есть одна проблема: 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
Эндрю Дрыга,


Я создал пакет для этого, если вы используете response
Martin Dawson

Ответы:


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, но я хотел написать что-нибудь, где у меня было бы много-много таких textarea(примерно столько же, сколько обычно было бы строк в большом текстовом документе). В этом случае это действительно медленно. (В Firefox это безумно медленно.) Поэтому я действительно хотел бы подход, который использует чистый CSS. Это было бы возможно с contenteditable, но я хочу, чтобы это было только открытым текстом.


13
Оно делает! Сделал jsfiddle для вас: jsfiddle.net/CbqFv. Теперь он работает в Chrome, Firefox и IE8, хотя в IE8 он немного затруднен. Когда вы увеличиваете или уменьшаете количество строк, это немного волнуется. Как вы, возможно, видели в плагине autoresize для jQuery, они обходят это путем клонирования текстовой области, устанавливая ее высоту равной auto вместо оригинала, а затем используя ее для установки высоты прокрутки оригинала. Я сделал это в этой обновленной скрипке: jsfiddle.net/CbqFv/2 Это решает проблему IE, но Firefox перестает работать.
Крис Москини

3
@ HelenNeely: Тогда не используйте идентификатор. Например, используйте класс и делайте то, что делает init для всех элементов этого класса. Это должно быть задачей для начинающих.
Panzi

3
@ DenilsonSá Если бы можно было только предположить, что используются только современные браузеры, лучше было бы использовать Интернет.
Panzi

2
Это не будет хорошо работать, если в IE11 включена полоса прокрутки. Если вы используете эту скрипку jsfiddle.net/CbqFv и вводите строки, пока не получите полосу прокрутки, вы увидите ее. Любые идеи?
kaljak

7
Это полностью нарушается, если текстовая область находится рядом с нижним концом страницы - все прыгает вперед и назад из-за 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()


ОБНОВЛЕНИЕ ТЕКСТАРЕА ВИА JAVASCRIPT

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

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

PRESET TEXTAREA ВЫСОТА

Чтобы исправить начальную высоту текстовой области, вам нужно будет добавить дополнительное условие:

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 - я помещаю текстовую область в модал Bootstrap! Так как модальный сначала скрыт, текстовая область в нем будет иметь значение 0 scrollHeight W
WTIFS

7
@ Обсидиан Фантастика !! (Вариант 3). Это this.style.height = 'auto';волшебное поведение исправить. Я был так расстроен, почему scrollHeight был таким странным в поведении. Высота до auto, а затем соответствие scrollHeight в том же цикле рендеринга, все еще поражает, как она «исправляет» эту проблему, хотя технически следует рисовать только вторую высоту.
бит

2
Сегодня я попробовал вариант 3 в Chrome, и мне пришлось сделать несколько настроек. 1) Он не всегда корректно изменяет размер, если у вас есть переход «высота» или «все» в текстовой области. Я бы порекомендовал не использовать переходы, которые влияют на высоту. 2) scrollHeight возвращал минимум высоты двух строк (возможно, потому что это значение по умолчанию для textareas в Chrome), но если вы измените this.style.height = 'auto'; to this.style.height = '0px'; и добавьте минимальную высоту, чтобы начальное состояние фактически не равнялось 0, scrollHeight правильно вернет один ряд высоты, когда это необходимо.
ZorroDeLaArena

3
@Obsidian Можете ли вы объяснить, как this.style.height = 'auto';исправляет поведение scrollHeight? Это просто волшебство.
Сидни

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

Не совсем уверен, но без этого текстовая область увеличивается слишком сильно. Я думаю, что это связано с тем, как вычисляются элементы scrollHeight.
Чим

1
Используйте несколько событий, чтобы сделать работу для широкой $('textarea.auto-resize').on('change cut paste drop keyup', function(){...})
истины

1
В Chrome 40 Win 8.1 прыгает как сумасшедший в текстах, которые длиннее, чем область просмотра. Оказывает это довольно непригодным.
tobibeer

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

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;свойство установлено, иначе текстовое поле увеличивается на 4 пикселя для каждого события onInput. Я провел около 3 часов, пока не понял, что это проблема.
AION

24

Лучшее решение (работает и коротко) для меня:

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

Он работает как брелок без каких-либо мерцаний с пастой (также с мышью), вырезает, вводит и сжимается до нужного размера.

Пожалуйста, посмотрите на jsFiddle .


Потрясающе !!! сделка в одну строку! глупый вопрос, как я могу добавить анимацию, когда она изменяет размер? как текстовое поле Сорта, мягко изменяющее размер, а не переход к размеру?
user2513846

1
@ user2513846 Похоже, это невозможно из-за многострочного редактирования. Я привел пример анимации размера текстовой области: jsfiddle.net/yk2g333e Как вы знаете, текстовый курсор перемещается вниз по линии или каретке, поэтому, если в этот момент нет паузы, анимировать нечего. Но пауза будет раздражать пользователя.
vatavale

1
@ user2513846 Однако, с еще одной пустой строкой в ​​конце текстовой области, можно иметь плавную анимацию: jsfiddle.net/p23erdfr
vatavale

16

Вы используете более высокое значение текущего clientHeight и содержимого scrollHeight. Когда вы уменьшаете scrollHeight, удаляя содержимое, вычисляемая область не может уменьшаться, потому что clientHeight, ранее установленный style.height, держит его открытым. Вместо этого вы можете взять max () из scrollHeight и минимальное значение высоты, которое вы предварительно определили или рассчитали из textarea.rows.

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

Другой возможный альтернативный подход, позволяющий избежать проблемы, если важно, чтобы он работал более широко, может заключаться в использовании скрытого элемента div, имеющего ширину, равную ширине текстовой области, и установленного в том же шрифте. При keyup вы копируете текст из текстовой области в текстовый узел в скрытом div (не забывая заменить '\ n' на разрыв строки и экранировать '<' / '&' правильно, если вы используете innerHTML). Затем просто измерив смещение divHeight, вы получите необходимую высоту.


1
Какие браузеры должны иметь проблемы с scrollHeightтекстовыми сообщениями? Прекрасно работает с текущими версиями IE, Firefox и Opera ...
Кристоф

1
Единственное, что мне нужно передать, - это Konqueror, который возвращает clientHeight как scrollHeight. Это поведение, которое вы можете ожидать, если браузер не применяет блочную модель CSS к внутренним элементам виджетов, что они не всегда делали, и стандарт не говорит, что они должны это делать.
Бобинце

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 остаются маленькими. Вы должны вызвать inputсобытие во время инициализации в цикле foreach.
Аякс

11

авто размер

https://github.com/jackmoore/autosize

Просто работает, автономно, популярен (3.0k + звезды GitHub по состоянию на октябрь 2018), доступен на cdnjs ) и легкий (~ 3.5k). Демо - версия:

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

Кстати, если вы используете редактор ACE, используйте maxLines: Infinity: Автоматически настроить высоту содержимого в редакторе Ace Cloud 9


2
Версия 2 была выпущена в феврале 2015 года. Она стала проще и больше не зависит от jQuery
хрустящий

Извините, это работает. Может быть, я был в другом браузере ... так что, думаю, будет лучше, если вы проигнорируете мой комментарий ..
Тони Мишель Каубе

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

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

7

Нашел один лайнер отсюда ;

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

6

Кто-нибудь посчитал приемлемым? Нет необходимости возиться с прокруткой, и единственное, что мне нравится в JS, - это если вы планируете сохранять данные в режиме размытия ... и, видимо, оно совместимо во всех популярных браузерах: http://caniuse.com/#feat = contenteditable

Просто сделайте так, чтобы оно выглядело как текстовое поле, и оно автоматически изменится ... Сделайте минимальную высоту желаемой высоты текста и сделайте это.

Что хорошо в этом подходе, так это то, что вы можете сохранять теги в некоторых браузерах.

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> опускаются при использовании [dom-element].innerText. @WebmasterG ИМХО, было бы неплохо опустить jquery (для прозрачности) и включить пример на этой странице через исполняемый фрагмент кода вместо jsfiddle.
Adabru

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в preи позволить CSS убедиться, что они имеют одинаковый размер.

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

Просто убедитесь, что preразмер шрифта такой же, как у textarea.


1
« Просто убедитесь, что у preнего тот же размер шрифта, что и уtextarea » - им нужно одинаковое 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. Когда атрибут стиля textareas displayизменяется, например, когда он переходит из none(скрытого) вblock
  3. Когда значение textareaизменяется программно

Обратите внимание, что использование window.getComputedStyleили получение currentStyleможет быть несколько вычислительно дорогим, поэтому вы можете вместо этого кэшировать результат.

Работает для IE6, поэтому я очень надеюсь, что это достаточно хорошая поддержка.


4

В качестве другого подхода вы можете использовать a, <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 Да, но два ответа не совпадают. Тойота делает красные машины, и Форд делает красные машины, но они разные, не так ли? Если вам больше нравится другой ответ, тогда иди с ним. Но есть те, кто больше ценит мой ответ и идет с ним. Наличие разных вариантов - это хорошо.
Расил Хилан

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

работает до тех пор, пока ваши строки не переполняются - тогда они не будут соответствовать.
Томаш Кафка

работает из коробки, отлично (firefox 72)
Mikeys4u

2

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

<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 .live()устарела. api.jquery.com/live Обычно вы хотите использовать .on()вместо этого.
Люк

2

Я не знаю, упоминал ли кто-нибудь об этом, но в некоторых случаях можно изменить высоту с помощью атрибутов строк.

textarea.setAttribute('rows',breaks);

демонстрация


1
Это работает, только если у вас есть white-space: nowrap;. Когда строка переносится на другую строку без разрыва строки, текстовая область больше не будет корректно корректироваться.
Йети

2

Вот директива angularjs для ответа Панзи.

 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 - это обеспечит инициализацию модели (не нужно указывать миллисекунды - она ​​будет выполнена после цикла дугового дайджеста). Также element = element [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.

Захватить текст

@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

Некоторые ответы здесь не учитывают отступы.

Предполагая, что у вас есть максимальная высота, которую вы не хотите проходить, это сработало для меня:

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

Это должен быть принятый ответ, хотя этого достаточно, чтобы прослушать события «keyup»
Боб Росс

1

моя реализация очень проста, посчитайте количество строк на входе (и минимум 2 строки, чтобы показать, что это текстовая область):

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

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

(и это работает с ручкой ручного изменения размера браузера, например)


2
Это работает только в том случае, если вы разбиваете строку нажатием «enter». Если ваш текст длиннее ширины текстовой области, но вы не нажимаете «ввод», он не расширяется.
Наталия Ксавье

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

Вы можете использовать этот код:

Coffescript:

jQuery.fn.extend autoHeightTextarea: ->
  autoHeightTextarea_ = (element) ->
    jQuery(element).css(
      'height': 'auto'
      'overflow-y': 'hidden').height element.scrollHeight

  @each ->
    autoHeightTextarea_(@).on 'input', ->
      autoHeightTextarea_ @

$('textarea_class_or_id`').autoHeightTextarea()

Javascript

jQuery.fn.extend({
  autoHeightTextarea: function() {
    var autoHeightTextarea_;
    autoHeightTextarea_ = function(element) {
      return jQuery(element).css({
        'height': 'auto',
        'overflow-y': 'hidden'
      }).height(element.scrollHeight);
    };
    return this.each(function() {
      return autoHeightTextarea_(this).on('input', function() {
        return autoHeightTextarea_(this);
      });
    });
  }
});

$('textarea_class_or_id`').autoHeightTextarea();
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.