Edited at

【JSわずか5行】textareaの高さを自動調節する超簡単な方法

javascript textarea 自動調整」とググると、その方法を解説したページがいろいろ出てきます。しかし、中には、文章量が減ったときに自動で低くならないものや、僕のようなペーペーJavaScripterが見ても「???」となるようなコードを使っていたりする場合があります。

ぺーぺーにも分かりやすく、文章量の増減に応じて高さを自動調節できるコードをここでは紹介します。


とりまコードを


HTML

<textarea rows="1" cols="30" class="sample"></textarea>



JavaScript

const sampleTextarea = document.querySelector('.sample');

sampleTextarea.addEventListener('input', () => {
sampleTextarea.style.height = "20px";
sampleTextarea.style.height = sampleTextarea.scrollHeight + "px";
})

サンプルはCodePenで確認できます。


コードの説明


textarea要素を取得


JavaScript

   const sampleTextarea = document.querySelector('.sample');

// sampleTextarea.addEventListener('input', () => {
// sampleTextarea.style.height = "20px";
// sampleTextarea.style.height = sampleTextarea.scrollHeight + "px";
// })


inputイベントを設定

textarea要素にinputイベントを設定します。textareaに文字を入力するたびにイベントが発生するようにします。


JavaScript

// const sampleTextarea = document.querySelector('.sample');

sampleTextarea.addEventListener('input', () => {
// sampleTextarea.style.height = "20px";
// sampleTextarea.style.height = sampleTextarea.scrollHeight + "px";
})


DOM input イベントは、<input><textarea>要素の値が変更された場合に、同期的に発生します。

input - イベントリファレンス | MDN


input/JavaScript - ホームページ入門サイトでも分かりやすく解説しています。


textareaの高さを自動で調整する


JavaScript

// const sampleTextarea = document.querySelector('.sample');

// sampleTextarea.addEventListener('input', () => {
sampleTextarea.style.height = "20px";
sampleTextarea.style.height = sampleTextarea.scrollHeight + "px";
// })

まずは、scrollHeightプロパティから説明をします。scrollHeightプロパティは今見えている部分とスクロールしなくては見えない部分の両方を含めた要素全体の高さです。


(Element.scrollHeightは)あふれた(overflowした)画面上に表示されていないコンテンツを含む要素の内容の高さを表します。 scrollHeightの値は、その要素が垂直スクロールバーを使用せずに、 要素の全てのコンテンツを見せるために収めるのに必要なclientHeightの最小値と同じ値になります。

.scrollHeight | JavaScript 日本語リファレンス | js STUDIO


textareaで文字が右端に来て折り返されるごとに行数は増えて、要素全体の高さが大きくなるので、scrollHeightの値は大きくなります。

1560849305272.gif

だから、textareaの高さにscrollHeightの値を設定します。


scrollHeightの値を指定するだけでいいんじゃないの?

それだと問題があります。例えば、複数行の文字を一気に消したときに高さが縮まりません。

1560858819384.gif

また、文字を1文字ずつ消すと謎の動きをします。

1560858984287.gif

このような問題を起きないようにするために20pxを指定しています。


なんで20px?

結論から言うと、20pxである必要はありません。

textareaの高さにscrollHeightの値を設定する前に、あえて十分に小さい値を高さとして設定します。すると、scrollHeightの値は要素の中身をスクロールなしに見せるための最小の値となります。こうしてからtextareaの高さにscrollHeightの値を設定することで、textareaがその中身の大きさに適したサイズに調整されます。

今回のコードでは「十分に小さい値」として「20px」を設定しているだけです。textareaになにも入力していない状態のときの高さより小さい値であればどの値でも大丈夫です。


改めて全体のコードを


JavaScript

const sampleTextarea = document.querySelector('.sample');

sampleTextarea.addEventListener('input', () => {
sampleTextarea.style.height = "20px";
sampleTextarea.style.height = sampleTextarea.scrollHeight + "px";
})

CodePenでデモを確認できます


応用1. 複数のtextareaを自動調節

for文を使うだけです。


HTML

<textarea rows="1" cols="30" class="sample" autofocus></textarea>

<textarea rows="1" cols="30" class="sample"></textarea>
<textarea rows="1" cols="30" class="sample"></textarea>
<textarea rows="1" cols="30" class="sample"></textarea>


JavaScript

const sampleTextarea = document.querySelectorAll('.sample');

for(let i = 0; i < sampleTextarea.length; i++) {
sampleTextarea[i].addEventListener('input', () => {
sampleTextarea[i].style.height = "20px";
sampleTextarea[i].style.height = sampleTextarea[i].scrollHeight + "px";
})
}

デモはこちらのCodePenで確認できます。


応用2. デフォルトで数行分の高さを持たせる

textareaに対してmin-heightを指定するだけです。


CSS

.sample {

min-height: 200px;
}

デモはこちらのCodePenで確認できます。


おわりに

間違っている点や改善案などがございましたら、コメント欄にてご教授ください。