Бесплатный вебинар
«как найти любимую работу»
Подарки на 150 000 ₽ за участие
Живой эфир
Записи не будет!
00:00:00:00
дн.ч.мин.сек.

Авторазмер textarea по содержимому с помощью CSS

Быстрый ответ

Настройка автоматического изменения размеров элемента <textarea> в соответствии с его содержимым, используя только CSS, невыполнима. Но вместо этого, применение простого JavaScript-скрипта в связке с приёмом использования вспомогательного скрытого <div> можно считать изящным и ненавязчивым решением данной задачи.

HTML
Скопировать код
<div style="position:relative;">
  <textarea class="auto-expand" style="min-height:40px; height:auto; overflow:hidden; resize:none;"></textarea>
  <!-- Невидимый помощник зеркальный div всегда с вами -->
  <div class="mirror-text" style="white-space:pre-wrap; visibility:hidden; position:absolute; z-index:-1;"></div>
</div>
JS
Скопировать код
// Зеркальный div функционирует как отражение для мяча — всегда готов поддержать
document.querySelector('.auto-expand').addEventListener('input', function() {
  document.querySelector('.mirror-text').textContent = this.value;
  this.style.height = 'auto';
  this.style.height = this.scrollHeight + 'px';
});

<div class="mirror-text"> незримо повторяет поведение textarea и точно копирует его размеры.

Кинга Идем в IT: пошаговый план для смены профессии

Почему только на CSS не получится

Реализация динамического изменения размеров textarea только при помощи CSS невозможна, так как, в отличие от JavaScript, CSS не предусматривает функционал для адаптации под содержимое блока. Известные обходные пути, например, overflow:auto или resize:vertical, не решают проблему, ибо или требуют активности со стороны пользователя, или остаются статичными.

Атрибут 'contenteditable' — наше туз в рукаве

Если использование JavaScript не вызывает отторжения, атрибут contenteditable может с успехом заменить <textarea>. Он позволяет делать любой элемент редактируемым и автоматически подгонять его размеры под содержимое. Однако, помните об обязательности очистки введённых данных для предотвращения HTML-инъекций.

HTML
Скопировать код
<div contenteditable="true" style="min-height:40px; max-height:200px; overflow:auto;">
  Разместите редактируемый текст здесь
</div>

Такой блок будет расширяться пропорционально его содержимому, однако для получения данных из div при отправке формы не обойтись без JavaScript.

Подробнее об этом расскажет наш спикер на видео
skypro youtube speaker

Повышаем удобство использования

Несмотря на присущие чистому CSS ограничения, настройка размеров textarea при помощи атрибута resize:vertical делает этот элемент более удобным в использовании.

CSS
Скопировать код
.auto-expand {
  min-height: 40px;
  max-height: 200px;
  resize: vertical;
  /* Знакомы ли вы с регулируемыми по высоте сидениями в машине? Удобно, не так ли? */
}

Атрибут rows определяет минимальную высоту поля ввода:

HTML
Скопировать код
<textarea rows="3"></textarea>

Атрибут maxLength, хотя и не влияет напрямую на размеры, ограничивает количество текста и способствует его оптимальному размещению.

Визуализация

Воспринимайте ваш textarea как контейнер, который гибко подстраивается под свое содержимое:

Markdown
Скопировать код
До:           После:
+---------+   +-----------------+
| Текст   |   | Текст точно     |
| здесь   |   | укладывается,   |
+---------+   | лишнего нет.     |
              +-----------------+

Будь то текст или абзац, содержимое эффективно заполняет контейнер.

Markdown
Скопировать код
📦 <-(Текст)     | 📦<----(Больше текста)-----> | 📦<---------(Ещё больше текста)--------->
 Маленький объём   Средний объём – как раз то, что нужно!    Большой объём, вмещающий всё необходимое

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

На практике: Применение в реальных условиях

Решение для динамического изменения размеров textarea на основе исключительно CSS остается недостижимой целью, тем не менее минимальный объём JavaScript, необходимый для этой задачи, представляет собой допустимый и разумный компромисс.

Эффективный JavaScript

Здесь используемый JavaScript выступает в роли однократно установленного прослушивателя событий, который обеспечивает изменение размеров textarea по мере того, как пользователь вводит текст.

Обработка отправления форм

При использовании атрибута contenteditable следует помнить, что для сохранения данных на сервере потребуется создать скрытый элемент <input>:

HTML
Скопировать код
<form>
  <div contenteditable="true" id="editable"></div>
  <input type="hidden" name="textareaContent" id="hiddenInput">
</form>

Затем потребуется применить JavaScript для синхронизации содержимого редактируемого блока с значением скрытого поля ввода в момент отправки формы.

Стилизация с помощью CSS

При помощи CSS-переменных упрощается и становится более управляемым процесс стилизации textarea и вспомогательного div:

CSS
Скопировать код
:root {
  --textarea-font-size: 16px;
  --textarea-line-height: 1.5;
  --textarea-padding: 10px;
}

.auto-expand,
.mirror-text {
  font-size: var(--textarea-font-size);
  line-height: var(--textarea-line-height);
  padding: var(--textarea-padding);
  /* В стиле "Copy-paste"? CSS-переменные говорят "нет". */
}

Полезные материалы

  1. Полное руководство по Flexbox | CSS-Tricks — Всё, что нужно знать для изучения flexbox.
  2. resize | CSS-Tricks — Подробное описание свойства resize, позволяющего изменять размеры элементов.
  3. <textarea>: элемент текстового поля — MDN — Документация MDN по элементу <textarea>.
  4. Использование пользовательских свойств CSS — MDN — Введение в применение CSS-переменных для создания гибкого дизайна.
  5. Создание авторазмерного текстового поля — Stack Overflow — Обсуждение в сообществе о текстовых полях с автоматической регулировкой размера.
  6. Can I use... Support tables for HTML5, CSS3, etc — Удобный ресурс для проверки поддержки браузерами функций CSS.
Проверь как ты усвоил материалы статьи
Пройди тест и узнай насколько ты лучше других читателей
Почему невозможно реализовать авторазмер textarea только с помощью CSS?
1 / 5