Создание текстовой области с автоматическим изменением размера
Был еще один поток об этом, который я попробовал. Но есть одна проблема: 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 )
};
}
54 ответа
Это работает для меня (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
s (примерно столько же, сколько обычно бывает строк в большом текстовом документе). В этом случае это действительно медленно. (В Firefox это безумно медленно.) Поэтому я действительно хотел бы подход, который использует чистый CSS. Это было бы возможно с contenteditable
, но я хочу, чтобы это было только для открытого текста.
ПОЛНОЕ ЕЩЕ ПРОСТОЕ РЕШЕНИЕ
Обновлено 23/08/2017 (улучшена поддержка браузеров для мобильных телефонов и планшетов)
Следующий код будет работать:
- На клавишном вводе.
- Со вставленным текстом (щелкните правой кнопкой мыши и Ctrl+ V).
- С вырезанным текстом (щелкните правой кнопкой мыши и Ctrl+ X).
- С предварительно загруженным текстом.
- Со всем сайтом textarea (многострочного текстового поля).
- С Firefox (протестирован v31-55).
- С Chrome (проверено v37-60).
- С IE (проверен v9-v11).
- С Edge (проверено v14-v15).
- С IOS Safari.
- С браузером Android.
- С строгим режимом JavaScript.
- Проверен ли w3c.
- И оптимизирован и эффективен.
ВАРИАНТ 1 (с помощью jQuery)
Этот код требует jQuery и был протестирован и работает с 1.7.2 - 3.2.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://code.jquery.com/jquery-3.2.1.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>
ВАРИАНТ 2 (Чистый JavaScript)
Просто (добавьте этот JavaScript в ваш основной файл сценария и забудьте об этом.)
var tx = document.getElementsByTagName('textarea');
for (var 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>
ВАРИАНТ 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');
Решение 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/
Нашел один лайнер отсюда;
<textarea name="text" oninput="this.style.height = ''; this.style.height = this.scrollHeight +'px'"></textarea>
<!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.
Редактировать: keydown работает лучше, чем keyup
Редактировать: объявить функцию перед использованием
Изменить: ввод работает лучше, чем нажатие клавиши (thnx @ WASD42 & @ MA-Maddin)
Лучшее решение (работает и коротко) для меня:
$(document).on('input', 'textarea', function () {
$(this).outerHeight(38).outerHeight(this.scrollHeight); // 38 or '1em' -min-height
});
Он работает как брелок без каких-либо мерцаний с пастой (также с мышью), вырезает, вводит и сжимается до нужного размера.
Пожалуйста, посмотрите на jsFiddle.
Если вам не нужно поддерживать 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 I’ll resize.</textarea>
Вы можете прочитать больше о том, как это работает, в моем блоге.
Вы используете более высокое значение текущего 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, вы получите необходимую высоту.
авто размер
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
В качестве другого подхода вы можете использовать <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
в скрытое поле, которое затем будет автоматически отправлено вместе с формой.
Кто-нибудь посчитал приемлемым? Нет необходимости возиться с прокруткой, и единственное, что мне нравится в JS, - это если вы планируете сохранять данные на размытие... и, очевидно, оно совместимо во всех популярных браузерах: http://caniuse.co m/
Просто сделайте так, чтобы оно выглядело как текстовое поле, и оно автоматически изменится... Сделайте минимальную высоту предпочитаемой высоты текста и сделайте это.
Что хорошо в этом подходе, так это то, что вы можете сохранять теги на некоторых браузерах.
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>
Есть немного другой подход.
<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
,
Следующее работает для вырезания, вставки и т. Д., Независимо от того, выполняются ли эти действия с помощью мыши, сочетания клавиш, выбора параметра в строке меню... в нескольких ответах используется аналогичный подход, но они не учитывают размер, поэтому они неправильно применяют стиль 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
функционировать в еще нескольких обстоятельствах:
- Окно изменения размера событий, если ширина
textarea
изменяется с изменением размера окна или другими событиями, которые изменяют ширину текстовой области - Когда
textarea
"sdisplay
атрибут стиля меняется, например, когда он идет отnone
(скрыто)block
- Когда значение
textarea
изменяется программно
Обратите внимание, что с помощью window.getComputedStyle
или получать currentStyle
может быть несколько вычислительно дорогим, поэтому вы можете вместо этого кэшировать результат.
Работает на IE6, поэтому я очень надеюсь, что это достаточно хорошая поддержка.
Это простой способ сделать это с помощью React.
...
const textareaRef = useRef();
const handleChange = (e) => {
textareaRef.current.style.height = "auto";
textareaRef.current.style.height = textareaRef.current.scrollHeight + "px";
};
return <textarea ref={textareaRef} onChange={handleChange} />;
Я использовал следующий код для нескольких текстовых областей. Отлично работает в 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>
Немного исправлений. Отлично работает в опере
$('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;
});
Вот директива 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>
Вы можете использовать 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>
Я не знаю, упоминал ли кто-нибудь об этом, но в некоторых случаях можно изменить высоту с помощью атрибутов строк.
textarea.setAttribute('rows',breaks);
Улучшенное отзывчивое чистое решение JS со вторым вариантом user2120261
Следующее также касается нижнего заполнения, а также изменения размера окна. Таким образом, это почти идеальное решение для меня. Большое ему спасибо.
Примечание : есть странная проблема с jsfiddle, когда текстовое поле слишком высоко, а внизу слишком много места, но копирование и вставка точного кода в пустой HTML-файл работает отлично.
Однако есть небольшая проблема, когда на странице появляется полоса прокрутки, а текстовое поле сжимается и оборачивает текст и создает новую строку. Вышеупомянутая функция не принимает это во внимание, и я задал вопрос , но, похоже, никто не знает решения. Если есть предложения по решению вопроса, буду очень рад.
Я знаю короткий и правильный способ реализации этого с помощью 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>
Моя реализация очень проста, подсчитайте количество строк во вводе (и минимум 2 строки, чтобы показать, что это текстовое поле):
textarea.rows = Math.max(2, textarea.value.split("\n").length) // # oninput
полный рабочий пример со стимулом: https://jsbin.com/kajosolini/1/edit?html,js,output
(и это работает, например, с ручным изменением размера браузера)
Еще более простой и понятный подход заключается в следующем:
// 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
Тем, кто хочет добиться того же в новых версиях Angular.
Возьмите 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>
Я также добавляю еще один вариант использования, который может пригодиться некоторым пользователям, читающим поток, когда пользователь хочет увеличить высоту текстовой области до определенной высоты, а затем 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';
}
}
Некоторые ответы здесь не учитывают отступы.
Предполагая, что у вас есть максимальная высота, которую вы не хотите проходить, это сработало для меня:
// 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);
Я рекомендую библиотеку 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)
}
Ни один из ответов, похоже, не работает. Но этот работает для меня: 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();
Принятый ответ работает нормально. Но это очень много кода для этой простой функции. Приведенный ниже код поможет.
$(document).on("keypress", "textarea", function (e) {
var height = $(this).css("height");
var iScrollHeight = $(this).prop("scrollHeight");
$(this).css('height',iScrollHeight);
});
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();
}