Chupurnov Valeriy
Chupurnov Valeriy
Front End Engineer

КДПВ

Автосайз textarea

На этом блоге я пишу текст в обычном textarea, безо всяких визивигов. Это осознанный выбор. Markdown наше все. Но все же писать в просто textarea не столь удобно. Хочется автосайз и несколько шорткатов: чтобы CTRL+D и Tab работали как в обычных текстовых редакторах. Сейчас про автосайз. Самое первое нагугленое решение такое

function autosize(e) {
    e.target.style.height = '1px';
    e.target.style.height = e.target.scrollHeight + 'px';
}

function AutosizeTextArea() {
    return <textarea style={{overflowY: 'hidden'}} onInput={autosize}/>;
}

Если вы его запустите, то будете довольны. Работает превосходно.

До поры до времени. Все дело в этом 1px. Когда текст будет большой, то при уменьшении размера до 1-го пиксела, будет и изменен скрол страницы. При восстановлении размера, будет скрол обратно. Это раздражает.

Кажется тут пригодиться старая добрая техника запоминания скрола.

function autosize(e) {
    const scrollTop = window.scrollY;
    e.target.style.height = '1px';
    e.target.style.height = e.target.scrollHeight + 'px';
    window.scrollTo({ top: scrollTop });
}

Все работает прекрасно, но есть нюанс =)

Если у вас включено.

html {
    scroll-behavior: smooth;
}

А скорее всего оно у вас включено, то скролл вы все же увидите. Поэтому нужно эту штуку выключать, а потом включать:

function autosize(e) {
    document.documentElement.style.scrollBehavior = 'auto';
    const scrollTop = window.scrollY;
    e.target.style.height = '1px';
    e.target.style.height = e.target.scrollHeight + 'px';
    window.scrollTo({ top: scrollTop });
    document.documentElement.style.scrollBehavior = 'smooth';
}

Все работает превосходно. Как микро оптимизацию, я бы рекомендовал обернуть функцию в тротлер

const autosize = throttle((e) => {
    document.documentElement.style.scrollBehavior = 'auto';
    const scrollTop = window.scrollY;
    e.target.style.height = '1px';
    e.target.style.height = e.target.scrollHeight + 'px';
    window.scrollTo({ top: scrollTop });
    document.documentElement.style.scrollBehavior = 'smooth';
}, 100);

Вот и все. Всем добра!