Автосайз textarea​Казалось бы тривиальная задача: поле, которое бы автоматически меняло свою высоту в зависимости от внутреннего текста. Нечто подобное есть в редакторе, в котором я сейчас пишу этот текст ckeditor. Называется оно здесь autogrow и реализуется отдельным плагином. 

Да, разумеется и для нативных инпутов есть множество jQuery плагинов, которые выполняют возложенную на них функцию. 

Так сложилось, что мой блог - это не набор простых решений, типа берете такой плагин, подключаете и у Вас все работает. Нет. Я из тех людей, которых результаты запроса в гугле: "Как объединить два массива в, вызывают по меньшей мере негодование. 

Плеяда статей и вопросов на stackoverflow, с ответом: $.extend

У большинства сегодняшних web-developerov, нет ни тени сомнения, что jQuery подключен к любому проекту.

Я не из таких программистов. Есть такие области, в которых нет и не будет jQuery. К примеру, написание плагинов на другие библиотеки или программы. К примеру плагин на ckeditor, допускает использование лишь API самого редактора, потому, как само оно вести порядка 0.5Mb и библиотека в 0.09Mb будет излишней нагрузкой.

В таких ситуациях есть два пути: первый, написать все на API библиотеки, и второй сделать все на vanila.js 

При втором варианте, наш код будет легко портировать на любую другую библиотеку. Все заработает даже вовсе без нее.

Собственно ради чего это отступление - не стоит использовать плагин там, где все и так пишется в несколько строк кода.

Теперь к делу

Все готовые плагины, которые я встретил изучая этот вопрос, работают по одному принципу: создают div элемент, делают все его стили, размеры, шрифты и отступы идентичными textarea. Затем, прячут его, при этом делают это не при помощи display:none а с помощью visibility:hidden

Отличает одно от другого то, что у  display:none нельзя выяснить размер. А у visibility:hidden можно. Чтобы он не мешался, ему делают position:absolute; 

Потом на textarea вешается обработчик keyup,mouseup и change, который синхронизируется содержимое textarea и нашего div'а. Затем, в обратную сторону синхронизируется размер textarea с размером div'a. 

HTML

<div id="dummy"></div>
<textarea id="editor"></textarea>

CSS

#dummy{
 visibility:hidden;
 font-size:14px;
 line-height:14px;
 position:absolute;
 white-space: pre;
 word-break: break-all;
 padding:5px;
}
textarea{
 font-size:14px;
 line-height:14px;
 padding:5px;
}

JavaScript

var editor = document.getElementById('editor'),
      dummy = document.getElementById('dummy')
editor.addEventListener('keyup',function(){
   dummy.innerText = this.value;
   dummy.style.width = this.offsetWidth+'px';
   this.style.height = dummy.offsetHeight+'px';
},false)

Результат

 

//

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

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

Однако он очевидно «грязный», лишний элемент на странице, к тому же стили поля и блока не так уж и просто синхронизировать в реальном проекте.

 

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

var editor = document.getElementById('editor');
editor.addEventListener('keyup',function(){
   this.style.height = this.scrollHeight+this.offsetHeight+'px';
},false)

Результат

 

// 0) this.style.height = (this.clientHeight+olh)+'px'; },false) // ]]>

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

 

И наконец самое просто решение. Разбивать содержимое поля по /n/r и умножать на высоту строки. Полученную величину присваивать высоте поля. 

var editor = document.getElementById('editor');
editor.addEventListener('keyup',function(){
   this.style.height = parseInt(this.value.split(/[\n\r]/))*14+'px';
},false)

и css 

teaxtarea{
line-height:14px;
font-size:14px;
white-space: nowrap;// для того чтобы строки не переносились
}

Результат

 

//

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

Оставлять комментарии могут только зарегистрированные пользователи

Комментарии  

ывв
# ывв 25.01.2018 16:49
Писал код прямо тут, поэтому за работоспособность не ручаюсь. Но я и не претендую, важно понимать сам процесс. Этот способ самый действенный, и рабочий из предложенных мной.

не работает ни хрена, вот и не понимай процесс и не ручайся за работу. а ещё лучше не пиши больше